-
Notifications
You must be signed in to change notification settings - Fork 0
/
TLLineParser.m
109 lines (90 loc) · 2.34 KB
/
TLLineParser.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
//
// TLLineParser.m
// Tagalog
//
// Created by Nathan Vander Wilt on 10/10/09.
// Copyright 2009 __MyCompanyName__. All rights reserved.
//
#import "TLLineParser.h"
@interface TLLineParser ()
- (void)setParserError:(NSError*)newParserError;
@end
@implementation TLLineParser
@synthesize delegate;
@synthesize preserveEndings;
@synthesize lineNumber;
@synthesize parserError;
- (void)setParserError:(NSError*)newParserError {
[parserError autorelease];
parserError = [newParserError retain];
}
- (id)initWithContentsOfURL:(NSURL*)theFileURL {
self = [super init];
if (self) {
fileURL = [theFileURL copy];
}
return self;
}
- (void)dealloc {
[fileURL release];
delegate = nil;
[parserError release];
[super dealloc];
}
- (BOOL)parse {
NSError* internalError;
NSData* fileData = [NSData dataWithContentsOfURL:fileURL
options:NSMappedRead
error:&internalError];
if (!fileData) {
parserError = [internalError retain];
return NO;
}
const char* currentPosition = [fileData bytes];
const char* endPosition = currentPosition + [fileData length];
// process each line
lineNumber = 1;
const char* lineStart = currentPosition;
while (lineStart < endPosition) {
// scan to beginning of next line
const char* lineEnd = NULL;
while (currentPosition < endPosition) {
char byte = *currentPosition;
++currentPosition;
if (byte == '\n' || byte == '\r') {
// previous line is ending, set signal
if (!lineEnd) lineEnd = (currentPosition-1);
}
else if (lineEnd) {
// a new line has now begun, "push back" its first character
--currentPosition;
break;
}
}
ptrdiff_t lineLength = (lineEnd && ![self preserveEndings] ?
lineEnd : currentPosition) - lineStart;
NSData* lineData = [NSData dataWithBytesNoCopy:(void*)lineStart
length:lineLength
freeWhenDone:NO];
NSAutoreleasePool* pool = [NSAutoreleasePool new];
if ([[self delegate] respondsToSelector:@selector(lineParser:foundLine:)]) {
[[self delegate] lineParser:self foundLine:lineData];
}
[pool drain];
if (shouldAbort) {
// TODO: set error?
break;
}
if (!lineEnd) {
// if the line scan loop ended without newline, we break because it's EOF
break;
}
++lineNumber;
lineStart = currentPosition;
}
return YES;
}
- (void)abortParsing {
shouldAbort = YES;
}
@end