/*
 *	Filename: RegEx.m
 *	Created : Tue Dec  3 14:26:29 1996
 *	Author  : Vince DeMarco
 *	LastEditDate Was "Wed Jan 22 12:14:30 1997"
 */

#import "RegEx.h"
#import <Foundation/Foundation.h>
#import <strings.h>

@implementation RegEx

+ (void)initialize
{
    if (self == [RegEx class]) {
        [self setVersion:100];
    }
}

/* NSCoding Protocol */
- (void)encodeWithCoder:(NSCoder *)coder
{
    BOOL ignoreCase = [self ignoreCase];

        /* Do not call super.  NSObject does not conform to NSCoding. */
	/* [super encodeWithCoder:coder]; */
    [coder encodeObject:_pattern];
    [coder encodeValueOfObjCType:"C" at:&ignoreCase];
}

- (id)initWithCoder:(NSCoder *)coder
{
        /* Do not call super.  NSObject does not conform to NSCoding. */
	/* self = [super initWithCoder:coder]; */
    _pattern = [[coder decodeObject] retain];
    [coder decodeValueOfObjCType:"C" at:&_ignoreCase];

    if (_ignoreCase){
	regcomp(&_regex,[_pattern cString],REG_EXTENDED|REG_ICASE);
    }else{
	regcomp(&_regex,[_pattern cString],REG_EXTENDED);
    }

    return self;
}

/* NSCopying Protocol */
- (id)copyWithZone:(NSZone *)zone
{
    return [[[self class] allocWithZone:zone]
	                         initWithPattern:[self pattern]
	                              ignoreCase:[self ignoreCase]];
}


/* Rest of class */
+ (BOOL)validRegexPattern:(NSString *)pattern
{
    regex_t regex;

    if (regcomp(&regex,[pattern cString],REG_EXTENDED) != 0){
	return NO;
    }
    regfree(&regex);
    return YES;
}

+ (id)regexWithPattern:(NSString *)pattern
{
    return [[self class] regexWithPattern:pattern ignoreCase:NO];
}

+ (id)regexWithPattern:(NSString *)pattern ignoreCase:(BOOL)flag
{
    return [[[self class] alloc] initWithPattern:pattern ignoreCase:flag];
}

- (void)dealloc
{
    [_pattern release];
    regfree(&_regex);
    [super dealloc];
}

- initWithPattern:(NSString *)pattern ignoreCase:(BOOL)flag
{
    int ret;

    [super init];

    _pattern    = [pattern retain];
    _ignoreCase = flag;

    if (flag){
	ret = regcomp(&_regex,[_pattern cString],REG_EXTENDED|REG_ICASE);
    }else{
	ret = regcomp(&_regex,[_pattern cString],REG_EXTENDED);
    }

    if (ret != 0){
	char  *errbuf;
	size_t length;

	length = regerror(ret,&_regex,NULL,0);

	    /* errbuff leaks here so */
	errbuf = NSZoneMalloc([self zone],sizeof(char)*length);

	(void)regerror(ret,&_regex, errbuf, length);

	[NSException raise:NSInvalidArgumentException
		    format:@"Invalid regular expression pattern \"%@\" %s", pattern,errbuf];
	NSZoneFree([self zone],errbuf);
	[self release];
	return nil;
    }
    return self;

}

- initWithPattern:(NSString *)pattern
{
    return [self initWithPattern:pattern ignoreCase:NO];
}

- (NSString *)pattern
{
    return _pattern;
}

- (BOOL) ignoreCase
{
    return _ignoreCase;
}

- (NSString *)description
{
    return [NSString stringWithFormat:@"<%@>",[self pattern]];
}

- (BOOL)patternMatchesString:(NSString *)string
{
    if (regexec(&_regex,[string cString],0,NULL,0) == 0){
	return YES;
    }
    return NO;
}

- (NSArray *)stringWithComponents:(NSString *)matchString
{
    regmatch_t     *pmatch;
    const char     *string;
    int             i;
    int             err;
    NSMutableArray *array;

    string = [matchString cString];
    array  = [[[NSMutableArray allocWithZone:[self zone]] init] autorelease];

    pmatch = NSZoneCalloc([self zone],_regex.re_nsub+1,sizeof(regmatch_t));
    err = regexec(&_regex,string,_regex.re_nsub+1,pmatch,0);
    i = 1;
    while(pmatch[i].rm_so != -1){
	[array addObject:[NSString stringWithCString:string+pmatch[i].rm_so
				              length:(pmatch[i].rm_eo - pmatch[i].rm_so)]];
	i++;
    }
    NSZoneFree([self zone],pmatch);
    return array;
}

@end
