static NSCharacterSet *equalSignCharSet = nil;
static NSCharacterSet *commaCharSet = nil;
static NSCharacterSet *colonAndSemicolonCharSet = nil;
+static NSCharacterSet *colonSemicolonAndDquoteCharSet = nil;
static NSCharacterSet *whitespaceCharSet = nil;
static VSStringFormatter *stringFormatter = nil;
[[NSCharacterSet characterSetWithCharactersInString:@","] retain];
colonAndSemicolonCharSet =
[[NSCharacterSet characterSetWithCharactersInString:@":;"] retain];
+ colonSemicolonAndDquoteCharSet =
+ [[NSCharacterSet characterSetWithCharactersInString:@":;\""] retain];
whitespaceCharSet =
[[NSCharacterSet whitespaceCharacterSet] retain];
}
- (void)_parseLine:(NSString *)_line {
- NSScanner *scanner;
- NSString *tagName, *tagAttribute, *tagValue;
+ NSString *tagName, *tagValue;
NSMutableArray *tagAttributes;
+ NSRange r, todoRange;
+ unsigned length;
- scanner = [NSScanner scannerWithString:_line];
+ length = [_line length];
tagAttributes = [[NSMutableArray alloc] init];
-
- tagName = @"";
- [scanner scanUpToCharactersFromSet:colonAndSemicolonCharSet
- intoString:&tagName];
-
- while ([scanner scanString:@";" intoString:NULL]) {
- [scanner scanUpToCharactersFromSet:colonAndSemicolonCharSet
- intoString:&tagAttribute];
- [tagAttributes addObject:tagAttribute];
+ todoRange = NSMakeRange(0, length);
+ r = [_line rangeOfCharacterFromSet:colonAndSemicolonCharSet
+ options:0
+ range:todoRange];
+ tagName = [[_line substringToIndex:r.location] uppercaseString];
+ if([_line characterAtIndex:r.location] != ':') {
+ BOOL isAtEnd = NO, isInDquote = NO;
+ unsigned start = NSMaxRange(r);
+
+ todoRange = NSMakeRange(start, length - start);
+ while(!isAtEnd) {
+ BOOL skip = YES;
+
+ /* scan for parameters */
+ r = [_line rangeOfCharacterFromSet:colonSemicolonAndDquoteCharSet
+ options:0
+ range:todoRange];
+ /* first check if delimiter candidate is escaped */
+ if([_line characterAtIndex:(r.location - 1)] != '\\') {
+ unichar delimiter;
+ NSRange copyRange;
+
+ delimiter = [_line characterAtIndex:r.location];
+ if(delimiter == '\"') {
+ /* not a real delimiter - toggle isInDquote for proper escaping */
+ isInDquote = !isInDquote;
+ }
+ else {
+ if(!isInDquote) {
+ /* is a delimiter, which one? */
+ skip = NO;
+ if(delimiter == ':') {
+ isAtEnd = YES;
+ }
+ copyRange = NSMakeRange(start, r.location - start);
+ [tagAttributes addObject:[_line substringWithRange:copyRange]];
+ if(!isAtEnd) {
+ /* adjust start, todoRange */
+ start = NSMaxRange(r);
+ todoRange = NSMakeRange(start, length - start);
+ }
+ }
+ }
+ }
+ if(skip) {
+ /* adjust todoRange */
+ unsigned offset = NSMaxRange(r);
+ todoRange = NSMakeRange(offset, length - offset);
+ }
+ }
}
- [scanner scanString:@":" intoString:NULL];
- tagValue = [_line substringFromIndex:[scanner scanLocation]];
-
- //NSLog (@"%@ %@ %@",tagName,tagAttributes, tagValue);
-
- tagName = [tagName uppercaseString];
-
+ tagValue = [_line substringFromIndex:NSMaxRange(r)];
+
if ([tagName isEqualToString:@"BEGIN"]) {
id tag;