Skip to content

Commit fb6ee1c

Browse files
committed
Merge branch 'deploy/1.4.0' into productive
2 parents 68b70dd + de3f77c commit fb6ee1c

File tree

14 files changed

+299
-127
lines changed

14 files changed

+299
-127
lines changed

.swiftlint.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@ opt_in_rules:
44

55
disabled_rules:
66
- vertical_whitespace # Turn off until configurable to 2 newlines
7+
- cyclomatic_complexity
78

89
included:
910
- Sources
11+
- Tests
1012

1113
excluded:
1214
- Carthage

CSVImporter.podspec

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Pod::Spec.new do |s|
22

33
s.name = "CSVImporter"
4-
s.version = "1.3.1"
4+
s.version = "1.4.0"
55
s.summary = "Import CSV files line by line with ease."
66

77
s.description = <<-DESC
@@ -25,6 +25,5 @@ Pod::Spec.new do |s|
2525
s.source_files = "Sources", "Sources/**/*.swift"
2626
s.framework = "Foundation"
2727
s.dependency "HandySwift", "~> 1.3"
28-
s.dependency "FileKit", "~> 4.0"
2928

3029
end

CSVImporter.xcodeproj/project.pbxproj

Lines changed: 49 additions & 40 deletions
Large diffs are not rendered by default.

Cartfile

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,2 @@
1-
# Simple and expressive file management in Swift
2-
github "nvzqz/FileKit" "29e8c684fdb3018b3fe8ca6b84fe4fb06ef891bf"
3-
41
# Handy Swift features that didn't make it into the Swift standard library.
52
github "Flinesoft/HandySwift" ~> 1.3

Cartfile.private

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# The Swift (and Objective-C) testing framework.
2-
github "Quick/Quick" "master"
2+
github "Quick/Quick"
33

44
# A Matcher Framework for Swift and Objective-C
5-
github "Quick/Nimble" "master"
5+
github "Quick/Nimble"

Cartfile.resolved

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
github "nvzqz/FileKit" "29e8c684fdb3018b3fe8ca6b84fe4fb06ef891bf"
2-
github "Flinesoft/HandySwift" "1.3.0"
3-
github "Quick/Nimble" "76c4cb3567f3492c00e84a1000ba8622355c8323"
4-
github "Quick/Quick" "8e794df56011c6282f1074e8fd5c113d5f013e63"
1+
github "Flinesoft/HandySwift" "1.3.2"
2+
github "Quick/Nimble" "v5.1.1"
3+
github "Quick/Quick" "v1.0.0"

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212
alt="codebeat badge">
1313
</a>
1414
<a href="https://github.com/Flinesoft/CSVImporter/releases">
15-
<img src="https://img.shields.io/badge/Version-1.3.1-blue.svg"
16-
alt="Version: 1.3.1">
15+
<img src="https://img.shields.io/badge/Version-1.4.0-blue.svg"
16+
alt="Version: 1.4.0">
1717
</a>
1818
<img src="https://img.shields.io/badge/Swift-3-FFAC45.svg"
1919
alt="Swift: 3">
@@ -56,7 +56,7 @@ You can of course also just include this framework manually into your project by
5656
Simply add this line to your Cartfile:
5757

5858
```
59-
github "Flinesoft/CSVImporter" ~> 1.3
59+
github "Flinesoft/CSVImporter" ~> 1.4
6060
```
6161

6262
And run `carthage update`. Then drag & drop the HandySwift.framework in the Carthage/build folder to your project. Also do the same with the dependent frameworks `Filekit` and `HandySwift`. Now you can `import CSVImporter` in each class you want to use its features. Refer to the [Carthage README](https://github.com/Carthage/Carthage#adding-frameworks-to-an-application) for detailed / updated instructions.
@@ -71,7 +71,7 @@ platform :ios, '8.0'
7171
use_frameworks!
7272

7373
target 'MyAppTarget' do
74-
pod 'CSVImporter', '~> 1.3'
74+
pod 'CSVImporter', '~> 1.4'
7575
end
7676
```
7777

Sources/Code/CSVImporter.swift

Lines changed: 35 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -7,27 +7,26 @@
77
//
88

99
import Foundation
10-
import FileKit
1110
import HandySwift
1211

1312
/// An enum to represent the possible line endings of CSV files.
1413
public enum LineEnding: String {
15-
case NL = "\n"
16-
case CR = "\r"
17-
case CRLF = "\r\n"
18-
case Unknown = ""
14+
case nl = "\n"
15+
case cr = "\r"
16+
case crlf = "\r\n"
17+
case unknown = ""
1918
}
2019

2120
private let chunkSize = 4096
2221

2322
/// Importer for CSV files that maps your lines to a specified data structure.
24-
open class CSVImporter<T> {
25-
23+
public class CSVImporter<T> {
2624
// MARK: - Stored Instance Properties
2725

2826
let csvFile: TextFile
2927
let delimiter: String
3028
var lineEnding: LineEnding
29+
let encoding: String.Encoding
3130

3231
var lastProgressReport: Date?
3332

@@ -39,10 +38,7 @@ open class CSVImporter<T> {
3938
// MARK: - Computed Instance Properties
4039

4140
var shouldReportProgress: Bool {
42-
get {
43-
return self.progressClosure != nil &&
44-
(self.lastProgressReport == nil || Date().timeIntervalSince(self.lastProgressReport!) > 0.1)
45-
}
41+
return self.progressClosure != nil && (self.lastProgressReport == nil || Date().timeIntervalSince(self.lastProgressReport!) > 0.1)
4642
}
4743

4844

@@ -54,10 +50,11 @@ open class CSVImporter<T> {
5450
/// - path: The path to the CSV file to import.
5551
/// - delimiter: The delimiter used within the CSV file for separating fields. Defaults to ",".
5652
/// - lineEnding: The lineEnding of the file. If not specified will be determined automatically.
57-
public init(path: String, delimiter: String = ",", lineEnding: LineEnding = .Unknown) {
58-
self.csvFile = TextFile(path: Path(path))
53+
public init(path: String, delimiter: String = ",", lineEnding: LineEnding = .unknown, encoding: String.Encoding = .utf8) {
54+
self.csvFile = TextFile(path: path, encoding: encoding)
5955
self.delimiter = delimiter
6056
self.lineEnding = lineEnding
57+
self.encoding = encoding
6158

6259
delimiterQuoteDelimiter = "\(delimiter)\"\"\(delimiter)"
6360
delimiterDelimiter = delimiter+delimiter
@@ -70,9 +67,9 @@ open class CSVImporter<T> {
7067
/// - Parameters:
7168
/// - url: File URL for the CSV file to import.
7269
/// - delimiter: The delimiter used within the CSV file for separating fields. Defaults to ",".
73-
public convenience init?(url: URL, delimiter: String = ",", lineEnding: LineEnding = .Unknown) {
70+
public convenience init?(url: URL, delimiter: String = ",", lineEnding: LineEnding = .unknown, encoding: String.Encoding = .utf8) {
7471
guard url.isFileURL else { return nil }
75-
self.init(path: url.path, delimiter: delimiter, lineEnding: lineEnding)
72+
self.init(path: url.path, delimiter: delimiter, lineEnding: lineEnding, encoding: encoding)
7673
}
7774

7875
// MARK: - Instance Methods
@@ -82,7 +79,7 @@ open class CSVImporter<T> {
8279
/// - Parameters:
8380
/// - mapper: A closure to map the data received in a line to your data structure.
8481
/// - Returns: `self` to enable consecutive method calls (e.g. `importer.startImportingRecords {...}.onProgress {...}`).
85-
open func startImportingRecords(mapper closure: @escaping (_ recordValues: [String]) -> T) -> Self {
82+
public func startImportingRecords(mapper closure: @escaping (_ recordValues: [String]) -> T) -> Self {
8683
DispatchQueue.global(qos: DispatchQoS.QoSClass.userInitiated).async {
8784
var importedRecords: [T] = []
8885

@@ -109,7 +106,8 @@ open class CSVImporter<T> {
109106
/// - structure: A closure for doing something with the found structure within the first line of the CSV file.
110107
/// - recordMapper: A closure to map the dictionary data interpreted from a line to your data structure.
111108
/// - Returns: `self` to enable consecutive method calls (e.g. `importer.startImportingRecords {...}.onProgress {...}`).
112-
open func startImportingRecords(structure structureClosure: @escaping (_ headerValues: [String]) -> Void, recordMapper closure: @escaping (_ recordValues: [String: String]) -> T) -> Self {
109+
public func startImportingRecords(structure structureClosure: @escaping (_ headerValues: [String]) -> Void,
110+
recordMapper closure: @escaping (_ recordValues: [String: String]) -> T) -> Self {
113111
DispatchQueue.global(qos: DispatchQoS.QoSClass.userInitiated).async {
114112
var recordStructure: [String]?
115113
var importedRecords: [T] = []
@@ -147,37 +145,35 @@ open class CSVImporter<T> {
147145
/// - valuesInLine: The values found within a line.
148146
/// - Returns: `true` on finish or `false` if can't read file.
149147
func importLines(_ closure: (_ valuesInLine: [String]) -> Void) -> Bool {
150-
if lineEnding == .Unknown {
148+
if lineEnding == .unknown {
151149
lineEnding = lineEndingForFile()
152150
}
153-
if let csvStreamReader = self.csvFile.streamReader(lineEnding.rawValue) {
154-
for line in csvStreamReader {
155-
autoreleasepool {
156-
let valuesInLine = readValuesInLine(line)
157-
closure(valuesInLine)
158-
}
159-
}
151+
guard let csvStreamReader = self.csvFile.streamReader(lineEnding: lineEnding, chunkSize: chunkSize) else { return false }
160152

161-
return true
162-
} else {
163-
return false
153+
for line in csvStreamReader {
154+
autoreleasepool {
155+
let valuesInLine = readValuesInLine(line)
156+
closure(valuesInLine)
157+
}
164158
}
159+
160+
return true
165161
}
166162

167163
/// Determines the line ending for the CSV file
168164
///
169165
/// - Returns: the lineEnding for the CSV file or default of NL.
170166
fileprivate func lineEndingForFile() -> LineEnding {
171-
var lineEnding: LineEnding = .NL
167+
var lineEnding: LineEnding = .nl
172168
if let fileHandle = self.csvFile.handleForReading {
173169
if let data = (fileHandle.readData(ofLength: chunkSize) as NSData).mutableCopy() as? NSMutableData {
174-
if let contents = NSString(bytesNoCopy: data.mutableBytes, length: data.length, encoding: String.Encoding.utf8.rawValue, freeWhenDone: false) {
175-
if contents.contains(LineEnding.CRLF.rawValue) {
176-
lineEnding = .CRLF
177-
} else if contents.contains(LineEnding.NL.rawValue) {
178-
lineEnding = .NL
179-
} else if contents.contains(LineEnding.CR.rawValue) {
180-
lineEnding = .CR
170+
if let contents = NSString(bytesNoCopy: data.mutableBytes, length: data.length, encoding: encoding.rawValue, freeWhenDone: false) {
171+
if contents.contains(LineEnding.crlf.rawValue) {
172+
lineEnding = .crlf
173+
} else if contents.contains(LineEnding.nl.rawValue) {
174+
lineEnding = .nl
175+
} else if contents.contains(LineEnding.cr.rawValue) {
176+
lineEnding = .cr
181177
}
182178
}
183179
}
@@ -248,7 +244,7 @@ open class CSVImporter<T> {
248244
/// - Parameters:
249245
/// - closure: The closure to be called on failure.
250246
/// - Returns: `self` to enable consecutive method calls (e.g. `importer.startImportingRecords {...}.onProgress {...}`).
251-
open func onFail(_ closure: @escaping () -> Void) -> Self {
247+
public func onFail(_ closure: @escaping () -> Void) -> Self {
252248
self.failClosure = closure
253249
return self
254250
}
@@ -259,7 +255,7 @@ open class CSVImporter<T> {
259255
/// - Parameters:
260256
/// - closure: The closure to be called on progress. Takes the current count of imported lines as argument.
261257
/// - Returns: `self` to enable consecutive method calls (e.g. `importer.startImportingRecords {...}.onProgress {...}`).
262-
open func onProgress(_ closure: @escaping (_ importedDataLinesCount: Int) -> Void) -> Self {
258+
public func onProgress(_ closure: @escaping (_ importedDataLinesCount: Int) -> Void) -> Self {
263259
self.progressClosure = closure
264260
return self
265261
}
@@ -268,7 +264,7 @@ open class CSVImporter<T> {
268264
///
269265
/// - Parameters:
270266
/// - closure: The closure to be called on finish. Takes the array of all imported records mapped to as its argument.
271-
open func onFinish(_ closure: @escaping (_ importedRecords: [T]) -> Void) {
267+
public func onFinish(_ closure: @escaping (_ importedRecords: [T]) -> Void) {
272268
self.finishClosure = closure
273269
}
274270

@@ -293,7 +289,6 @@ open class CSVImporter<T> {
293289
}
294290
}
295291
}
296-
297292
}
298293

299294
func reportFinish(_ importedRecords: [T]) {
@@ -303,8 +298,6 @@ open class CSVImporter<T> {
303298
}
304299
}
305300
}
306-
307-
308301
}
309302

310303

0 commit comments

Comments
 (0)