@@ -31,84 +31,13 @@ public final class CSVReader: IteratorProtocol, Sequence {
3131 /// - If a CSV file has a header, the first row after a header (i.e. the first actual data row) will be the integer zero.
3232 /// - If a CSV file doesn't have a header, the first row to parse will also be zero.
3333 public var rowIndex : Int { let r = self . count. rows; return self . headers. isEmpty ? r : r - 1 }
34-
35- /// Creates a reader instance that will be used to parse the given `String`.
36- /// - parameter string: A `String` containing CSV formatted data.
37- /// - parameter configuration: Recipe detailing how to parse the CSV data (i.e. encoding, delimiters, etc.).
38- /// - throws: `CSVError<CSVReader>` exclusively.
39- public convenience init ( string: String , configuration: Configuration = . init( ) ) throws {
40- let buffer = ScalarBuffer ( reservingCapacity: 8 )
41- let iterator = ScalarIterator ( scalarIterator: string. unicodeScalars. makeIterator ( ) )
42- try self . init ( configuration: configuration, buffer: buffer, iterator: iterator)
43- }
44-
45- /// Creates a reader instance that will be used to parse the given data blob.
46- ///
47- /// If the configuration's encoding hasn't been set and the input data doesn't contain a Byte Order Marker (BOM), UTF8 is presumed.
48- /// - parameter data: A data blob containing CSV formatted data.
49- /// - parameter configuration: Recipe detailing how to parse the CSV data (i.e. encoding, delimiters, etc.).
50- /// - throws: `CSVError<CSVReader>` exclusively.
51- public convenience init ( data: Data , configuration: Configuration = . init( ) ) throws {
52- if configuration. presample, let dataEncoding = configuration. encoding {
53- // A. If the `presample` configuration has been set and the user has explicitly mark an encoding, then the data can parsed into a string.
54- guard let string = String ( data: data, encoding: dataEncoding) else { throw Error . mismatched ( encoding: dataEncoding) }
55- try self . init ( string: string, configuration: configuration)
56- } else {
57- // B. Otherwise, start parsing byte-by-byte.
58- let buffer = ScalarBuffer ( reservingCapacity: 8 )
59- // B.1. Check whether the input data has a BOM.
60- var dataIterator = data. makeIterator ( )
61- let ( inferredEncoding, unusedBytes) = String . Encoding. infer ( from: & dataIterator)
62- // B.2. Select the appropriate encoding depending from the user provided encoding (if any), and the BOM encoding (if any).
63- let encoding = try String . Encoding. selectFrom ( provided: configuration. encoding, inferred: inferredEncoding)
64- // B.3. Create the scalar iterator producing all `Unicode.Scalar`s from the data bytes.
65- let iterator = try ScalarIterator ( iterator: dataIterator, encoding: encoding, firstBytes: unusedBytes)
66- try self . init ( configuration: configuration, buffer: buffer, iterator: iterator)
67- }
68- }
69-
70- /// Creates a reader instance that will be used to parse the given CSV file.
71- ///
72- /// If the configuration's encoding hasn't been set and the input data doesn't contain a Byte Order Marker (BOM), UTF8 is presumed.
73- /// - parameter fileURL: The URL indicating the location of the file to be parsed.
74- /// - parameter configuration: Recipe detailing how to parse the CSV data (i.e. encoding, delimiters, etc.).
75- /// - throws: `CSVError<CSVReader>` exclusively.
76- public convenience init ( fileURL: URL , configuration: Configuration = . init( ) ) throws {
77- if configuration. presample {
78- // A. If the `presample` configuration has been set, the file can be completely load into memory.
79- try self . init ( data: try Data ( contentsOf: fileURL) , configuration: configuration) ; return
80- } else {
81- // B. Otherwise, create an input stream and start parsing byte-by-byte.
82- guard let stream = InputStream ( url: fileURL) else { throw Error . invalidFile ( url: fileURL) }
83- // B.1. Open the stream for usage.
84- assert ( stream. streamStatus == . notOpen)
85- stream. open ( )
86-
87- let ( encoding, unusedBytes) : ( String . Encoding , [ UInt8 ] )
88- do {
89- // B.2. Check whether the input data has a BOM.
90- let inferred = try String . Encoding. infer ( from: stream)
91- // B.3. Select the appropriate encoding depending from the user provided encoding (if any), and the BOM encoding (if any).
92- encoding = try String . Encoding. selectFrom ( provided: configuration. encoding, inferred: inferred. encoding)
93- unusedBytes = inferred. unusedBytes
94- } catch let error {
95- if stream. streamStatus != . closed { stream. close ( ) }
96- throw error
97- }
98-
99- // B.5. Create the scalar buffer & iterator producing all `Unicode.Scalar`s from the data bytes.
100- let buffer = ScalarBuffer ( reservingCapacity: 8 )
101- let iterator = try ScalarIterator ( stream: stream, encoding: encoding, chunk: 1024 , firstBytes: unusedBytes)
102- try self . init ( configuration: configuration, buffer: buffer, iterator: iterator)
103- }
104- }
10534
10635 /// Designated initializer for the CSV reader.
10736 /// - parameter configuration: Recipe detailing how to parse the CSV data (i.e. encoding, delimiters, etc.).
10837 /// - parameter buffer: A buffer storing in-flight `Unicode.Scalar`s.
10938 /// - parameter iterator: An iterator providing the CSV `Unicode.Scalar`s.
11039 /// - throws: `CSVError<CSVReader>` exclusively.
111- private init ( configuration: Configuration , buffer: ScalarBuffer , iterator: ScalarIterator ) throws {
40+ internal init ( configuration: Configuration , buffer: ScalarBuffer , iterator: ScalarIterator ) throws {
11241 self . configuration = configuration
11342 self . settings = try Settings ( configuration: configuration, iterator: iterator, buffer: buffer)
11443 ( self . headers, self . headerLookup) = ( . init( ) , nil )
@@ -127,7 +56,7 @@ public final class CSVReader: IteratorProtocol, Sequence {
12756 self . headers = headers
12857 self . count = ( rows: 1 , fields: headers. count)
12958// case .unknown:
130- // #warning("TODO")
59+ // #warning("TODO: ")
13160 }
13261 }
13362}
@@ -340,22 +269,6 @@ extension CSVReader {
340269}
341270
342271fileprivate extension CSVReader . Error {
343- /// The given `String.Encoding` is not yet supported by the library.
344- /// - parameter encoding: The desired byte representatoion.
345- static func mismatched( encoding: String . Encoding ) -> CSVError < CSVReader > {
346- . init( . invalidConfiguration,
347- reason: " The data blob didn't match the given string encoding. " ,
348- help: " Let the reader infer the encoding or make sure the data blob is correctly formatted. " ,
349- userInfo: [ " Encoding " : encoding] )
350- }
351- /// Error raised when an input stream cannot be created to the indicated file URL.
352- /// - parameter url: The URL address of the invalid file.
353- static func invalidFile( url: URL ) -> CSVError < CSVReader > {
354- . init( . streamFailure,
355- reason: " Creating an input stream to the given file URL failed. " ,
356- help: " Make sure the URL is valid and you are allowed to access the file. Alternatively set the configuration's presample or load the file in a data blob and use the reader's data initializer. " ,
357- userInfo: [ " File URL " : url] )
358- }
359272 /// Error raised when a header was required, but the line was empty.
360273 static func invalidEmptyHeader( ) -> CSVError < CSVReader > {
361274 . init( . invalidConfiguration,
0 commit comments