/* ** RegEx.m ** ** Copyright (c) 2002, 2003 ** ** Author: Yen-Ju Chen ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "RegEx.h" #include "GNUstep.h" @implementation RangeObject - (id) init { self = [super init]; _location = NSNotFound; _length = 0; return self; } - (void) dealloc { [super dealloc]; } - (unsigned int) location { return _location; } - (void) setLocation: (unsigned int) location; { _location = location; } - (unsigned int) length { return _length; } - (void) setLength: (unsigned int) length; { _length = length; } - (NSRange) range; { return NSMakeRange(_location, _length); } - (void) setRange: (NSRange) range; { _location = range.location; _length = range.length; } @end static NSMutableDictionary *patternsCache; @implementation RegExPattern + (RegExPattern *) regexPattern: (NSString *) pattern { id object; if (patternsCache == nil) { NSLog(@"Create patternCache"); patternsCache = [NSMutableDictionary new]; } if ((object = [patternsCache objectForKey: pattern])) { return object; } object = [[RegExPattern alloc] initWithPattern: pattern options: REG_EXTENDED]; [patternsCache setObject: object forKey: pattern]; return AUTORELEASE(object); } - (void) dealloc { regfree(preg); /* Not sure to release preg */ free(preg); [super dealloc]; } - (id) initWithPattern: (NSString *) pattern options: (unsigned int) mask { int result; char errbuf[255]; _mask = mask; preg = malloc(sizeof(regex_t)); result = regcomp(preg, [pattern cString], mask); if (result != 0) { regerror(result, preg, errbuf, 255); NSLog(@"RegEx Error: Couldn't compile regex %@: %s", pattern, errbuf); regfree(preg); return nil; } self = [super init]; return self; } - (regex_t *) pattern { return preg; } @end static regmatch_t pmatch[1]; static char errbuf[255]; @implementation RegExParser + (NSRange) rangeOfString:(NSString *) pattern inString: (NSString *) string { return [RegExParser rangeOfString: pattern inString: string range: NSMakeRange(0, [string length])]; } + (NSRange) rangeOfPattern: (RegExPattern *) pattern inString: (NSString *) string { return [RegExParser rangeOfPattern: pattern inString: string range: NSMakeRange(0, [string length])]; } + (NSRange) rangeOfString: (NSString *) pattern inString: (NSString *) string range: (NSRange) range; { return [RegExParser rangeOfPattern: [RegExPattern regexPattern: pattern] inString: string range: range]; } + (NSRange) rangeOfPattern: (RegExPattern *) pattern inString: (NSString *) string range: (NSRange) range { int result; int location, length; int mask = 0; /* Declare static above * regmatch_t pmatch[1]; * char errbuf[255]; */ NSAssert(range.location != NSNotFound, @"\nRange can't be NSNotFound"); NSAssert(range.location + range.length <= [string length], @"\nRange can't longer than string length"); NSAssert(range.location >= 0, @"\nRange can't less than 0"); /* Considering the situation of beginning line */ if (range.location != 0) mask = mask | REG_NOTBOL; if ((range.location + range.length) != [string length]) mask = mask | REG_NOTEOL; result = regexec([pattern pattern], [[string substringWithRange: range] cString], 1, pmatch, mask); if (result != 0) { if (result != REG_NOMATCH) { regerror(result, [pattern pattern], errbuf, 255); NSLog(@"RegEx Error: Couldn't match RegEx %s", errbuf); } return NSMakeRange(NSNotFound, 0); } location = range.location + pmatch->rm_so; length = pmatch->rm_eo - pmatch->rm_so; NSAssert (length >= 1, @"\nRegEx can't return null string"); return NSMakeRange(location, length); } - (id) initWithPattern: (NSString *) string options: (unsigned int)mask { RegExPattern *pattern = [[RegExPattern alloc] initWithPattern: string options: mask]; AUTORELEASE(pattern); return [self initWithPattern: pattern]; } - (id) initWithPattern: (RegExPattern *) pattern { self = [super init]; ASSIGN(_pattern, pattern); _string = nil; _range = NSMakeRange(NSNotFound, 0); _originalRange = NSMakeRange(NSNotFound, 0); _lastMatch = NSMakeRange(NSNotFound, 0); return self; } - (void) dealloc { RELEASE(_pattern); RELEASE(_string); [super dealloc]; } - (RegExPattern *) pattern { return _pattern; } - (void) setString: (NSString *) string { [self setString: string range: NSMakeRange(0, [string length])]; } - (void) setString: (NSString *) string range: (NSRange) range { ASSIGN(_string, string); _originalRange = range; [self reset]; } - (NSString *) string { return _string; } - (NSRange) range { return _originalRange; } - (void) reset { _range = _originalRange; _lastMatch = NSMakeRange(NSNotFound, 0); } @end