Commits

Dave DeLong committed 6f3010f

Cancelling a parser now results in the didFailWithError: callback getting executed.

This also includes cleanup to error codes and an updated README.

  • Participants
  • Parent commits 314d524

Comments (0)

Files changed (6)

 #import "CHCSVParser.h"
 #import "CHCSVWriter.h"
 #import "NSArray+CHCSVAdditions.h"
-#import "NSString+CHCSVAdditions.h"
+#import "NSString+CHCSVAdditions.h"
+
+extern NSString *const CHCSVErrorDomain;
+
+enum {
+    CHCSVErrorCodeGeneric = 0,
+    CHCSVErrorCodeInvalidStream,
+    CHCSVErrorCodeInvalidFormat,
+    CHCSVErrorCodeParsingCancelled
+};
+
+typedef NSInteger CHCSVErrorCode;

File CHCSVParser.m

  THE SOFTWARE.
  **/
 
-#import "CHCSVParser.h"
+#import "CHCSV.h"
 #define STRING_QUOTE @"\""
 #define STRING_BACKSLASH @"\\"
 
 #define UNICHAR_QUOTE '"'
 #define UNICHAR_BACKSLASH '\\'
 
+NSString *const CHCSVErrorDomain = @"com.davedelong.csv";
+
 enum {
 	CHCSVParserStateInsideFile = 0,
 	CHCSVParserStateInsideLine = 1,
     if (self) {
         csvReadStream = [readStream retain];
         [csvReadStream open];
+        
+        NSStreamStatus status = [csvReadStream streamStatus];
+        if (status != NSStreamStatusOpening &&
+            status != NSStreamStatusOpen &&
+            status != NSStreamStatusReading) {
+            if (anError) {
+                *anError = [NSError errorWithDomain:CHCSVErrorDomain code:CHCSVErrorCodeInvalidStream userInfo:[NSDictionary dictionaryWithObject:@"Unable to open file for reading" forKey:NSLocalizedDescriptionKey]];
+            }
+            [self release];
+            return nil;
+        }
 		
         chunkSize = 2048;
         
 
 - (id) initWithContentsOfCSVFile:(NSString *)aCSVFile usedEncoding:(NSStringEncoding *)usedEncoding error:(NSError **)anError {
     NSInputStream *readStream = [NSInputStream inputStreamWithFileAtPath:aCSVFile];
-    if (readStream == nil) {
-        if (anError) {
-            *anError = [NSError errorWithDomain:@"com.davedelong.csv" code:0 userInfo:[NSDictionary dictionaryWithObject:@"Unable to open file for reading" forKey:NSLocalizedDescriptionKey]];
-        }
-        [self release];
-        return nil;
-    }
     
     self = [self initWithStream:readStream usedEncoding:usedEncoding error:anError];
 	if (self) {
         if (readString == nil) {
             readLength--;
             if (readLength == 0) {
-                error = [[NSError alloc] initWithDomain:@"com.davedelong.csv" code:0 userInfo:[NSDictionary dictionaryWithObjectsAndKeys:
+                error = [[NSError alloc] initWithDomain:CHCSVErrorDomain code:CHCSVErrorCodeInvalidStream userInfo:[NSDictionary dictionaryWithObjectsAndKeys:
                                                                                                @"unable to interpret current chunk as a string", NSLocalizedDescriptionKey,
                                                                                                nil]];
                 break;
         nextChunk = [NSData dataWithBytes:bytes length:bytesRead];
     }
     @catch (NSException *e) {
-        error = [[NSError alloc] initWithDomain:@"com.davedelong.csv" code:0 userInfo:[NSDictionary dictionaryWithObjectsAndKeys:
+        error = [[NSError alloc] initWithDomain:CHCSVErrorDomain code:CHCSVErrorCodeInvalidStream userInfo:[NSDictionary dictionaryWithObjectsAndKeys:
                                                                                        e, NSUnderlyingErrorKey,
                                                                                        [e reason], NSLocalizedDescriptionKey,
                                                                                        nil]];
 	} else {
 		if (previousUnichar == UNICHAR_QUOTE && previousPreviousUnichar != UNICHAR_BACKSLASH && balancedQuotes == YES && balancedEscapes == YES) {
 			NSString *reason = [NSString stringWithFormat:@"Invalid CSV format on line #%lu immediately after \"%@\"", currentLine, currentField];
-			error = [[NSError alloc] initWithDomain:@"com.davedelong.csv" code:0 userInfo:[NSDictionary dictionaryWithObject:reason forKey:NSLocalizedDescriptionKey]];
+			error = [[NSError alloc] initWithDomain:CHCSVErrorDomain code:CHCSVErrorCodeInvalidFormat userInfo:[NSDictionary dictionaryWithObject:reason forKey:NSLocalizedDescriptionKey]];
 			return;
 		}
 		if (state != CHCSVParserStateInsideComment) {
 
 - (void) cancelParsing {
     SETSTATE(CHCSVParserStateCancelled)
+    error = [[NSError alloc] initWithDomain:CHCSVErrorDomain code:CHCSVErrorCodeParsingCancelled userInfo:nil];
 }
 
 @end

File CHCSVWriter.m

  THE SOFTWARE.
  **/
 
-#import "CHCSVWriter.h"
+#import "CHCSV.h"
 
 
 @implementation CHCSVWriter

File NSArray+CHCSVAdditions.m

  THE SOFTWARE.
  **/
 
-#import "NSArray+CHCSVAdditions.h"
-#import "CHCSVParser.h"
-#import "CHCSVWriter.h"
+#import "CHCSV.h"
 
 #pragma mark Support
 
 	for (id object in self) {
 		if ([object isKindOfClass:[NSArray class]] == NO) {
             if (error != NULL) {
-                *error = [NSError errorWithDomain:@"com.davedelong.csv" code:0 userInfo:[NSDictionary dictionaryWithObject:@"Invalid array structure" forKey:NSLocalizedDescriptionKey]];
+                *error = [NSError errorWithDomain:CHCSVErrorDomain code:CHCSVErrorCodeInvalidFormat userInfo:[NSDictionary dictionaryWithObject:@"Invalid array structure" forKey:NSLocalizedDescriptionKey]];
             }
             return NO;
         }

File NSString+CHCSVAdditions.m

  THE SOFTWARE.
  **/
 
-#import "NSString+CHCSVAdditions.h"
-#import "NSArray+CHCSVAdditions.h"
-#import "CHCSVParser.h"
+#import "CHCSV.h"
 
 @implementation NSString (CHCSVAdditions)
 

File README.markdown

 
 ##Usage
 
+In order to use `CHCSVParser`, you'll need to include the following five files in your project:
+
+- `CHCSV.h`
+- `CHCSVParser.*`
+- `CHCSVWriter.*`
+
+These four files are optional, though they do simplify things:
+
+- `NSArray+CHCSVAdditions.*`
+- `NSString+CHCSVAdditions.*`
 
 ###Parsing
-In order to parse CSV files, you'll need `CHCSVParser.h` and `CHCSVParser.m`.  A `CHCSVParser` works very similarly to an `NSXMLParser`, in that it synchronously parses the data and invokes delegate callback methods to let you know that it has found a field, or has finished reading a line, or has encountered a syntax error.
+A `CHCSVParser` works very similarly to an `NSXMLParser`, in that it synchronously parses the data and invokes delegate callback methods to let you know that it has found a field, or has finished reading a line, or has encountered a syntax error.
 
 A `CHCSVParser` can be created in one of three ways:
 
 `CHCSVParser` can be configured to parse other "character-seperated" file formats, such as "TSV" (tab-seperated).  You can change the delimiter of the parser prior to beginning parsing.  The delimiter can only be one character in length, and cannot be any newline character, `#`, `"`, or `\`.
 
 ###Writing
-In order to write data to a CSV file, you'll need `CHCSVWriter.h` and `CHCSVWriter.m`.  A `CHCSVWriter` has several methods for constructing CSV files:
+A `CHCSVWriter` has several methods for constructing CSV files:
 
 `-writeField:` accepts an object and writes its `-description` (after being properly escaped) out to the CSV file.  It will also write field seperator (`,`) if necessary.  You may pass an empty string (`@""`) or `nil` to write an empty field.
 
 Like `CHCSVParser`, `CHCSVWriter` can be customized with a delimiter other than `,` prior to beginning writing.
 
 ###Convenience Methods
-Included in the code is an `NSArray` category to simplify reading from and writing to CSV files.  In order to use these methods, you must include `CHCSVParser.*`, `CHCSVWriter.*`, and `NSArray+CHCSVAdditions.*` in your project (all six files).  This category adds many methods to `NSArray` to simplify the process of converting a file, string, or input stream into an `NSArray` of `NSArrays` of `NSStrings`.  There are also methods to write the array to a CSV file (or with a custom delimiter), or to convert it into an `NSString` of well-formed CSV.
+Included in the code is an `NSArray` category to simplify reading from and writing to CSV files.  In order to use these methods, you must also include `NSArray+CHCSVAdditions.*` in your project.  This category adds many methods to `NSArray` to simplify the process of converting a file, string, or input stream into an `NSArray` of `NSArrays` of `NSStrings`.  There are also methods to write the array to a CSV file (or with a custom delimiter), or to convert it into an `NSString` of well-formed CSV.
 
 There is also an `NSString` category to parse an `NSString` of CSV data into an `NSArray` of `NSArray` objects.  This method is `-[NSString CSVComponents]`.
 
 ###General Use
 
-The simplest use of `CHCSVParser` is to include all of the files in your project:
-
-- `CHCSV.h`
-- `CHCSVParser.h` and `CHCSVParser.m`
-- `CHCSVWriter.h` and `CHCSVWriter.m`
-- `NSArray+CHCSVAdditions.h` and `NSArray+CHCSVAdditions.m`
-- `NSString+CHCSVAdditions.h` and `NSString+CHCSVAdditions.m`
-
-Then to use any of the CSV parsing or writing functionality, simply `#import "CHCSV.h"` and use any of the classes and categories as you'd like.
+The simplest use of `CHCSVParser` is to include all of the files mentioned above in your project.  To use any of the CSV parsing or writing functionality, simply `#import "CHCSV.h"` and use any of the classes and categories as you'd like.
 
 
 ##Data Encoding