/*****
 NAME
	cregexp.m - source code for CRegExp class
 VERSION
	$Id$
 CHANGELOG
	$Log$
 */

#include <coconut/cregexp.h>
#include <coconut/cmemory.h>
#include <coconut/csystem.h>
#include <coconut/cerror.h>

#if !defined(REG_BASIC)
#  define	REG_BASIC	0
#endif

@implementation CRegExp

- init 
{
	compile_flag = REG_BASIC ;
	error_id = 0 ; /* no error */

	msg_buffer = [[CMemory alloc] initMemoryWithPage: 32] ;
	[CSystem checkPtr: msg_buffer] ;
	return [super init] ;
}

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

- setExtendedMode
{
	compile_flag |= REG_EXTENDED ;
	return nil ;
}

- setIgnoreCaseMode
{
	compile_flag |= REG_ICASE ;
	return nil ;
}

- setDotNotMatchNewlineMode
{
	compile_flag |= REG_NEWLINE ;
	return nil ;
}

- (id <PError>) compile: (const char *) pattern
{
	error_id = regcomp(&pattern_buffer, pattern, compile_flag) ;
	return error_id == 0 ? nil : [CError illegal_format] ;
}

- (id <PError>) match: (const char *) str start:(off_t *) start 
    stop:(off_t *) stop
{
	id <PError>	err ;
	regmatch_t	pmatch[1] ;

	error_id = regexec(&pattern_buffer, str, 1, pmatch, match_flag) ;
	if(error_id == 0) {
		*start = pmatch[0].rm_so ;
		*stop  = pmatch[0].rm_eo ;
		err = nil ;
	} else if(error_id == REG_NOMATCH)
		err = [CError not_matched] ; /* not matched */
	else
		err = [CError unknown] ; /* internal error */
	return err ;
}

- (const char *) getErrorStr 
{
	size_t	newsize ;
	size_t	cursize ;

	cursize = [msg_buffer size] ;
	newsize = regerror(error_id, &pattern_buffer, [msg_buffer ptr],cursize);
	if(newsize > cursize){
		[msg_buffer changeSize: newsize] ;
		regerror(error_id, &pattern_buffer, [msg_buffer ptr], 
		  [msg_buffer size]) ;
	}
	return [msg_buffer ptr] ;
}

@end

