Implement error handling
This commit is contained in:
parent
1d72634a03
commit
eb38710590
|
@ -62,7 +62,7 @@ internal class BinaryReader {
|
|||
stream.open()
|
||||
}
|
||||
if stream.streamStatus != .open {
|
||||
throw CSVError.cannotOpenFile
|
||||
throw CSVError.cannotOpenStream
|
||||
}
|
||||
|
||||
let readCount = stream.read(tempBuffer, maxLength: tempBufferSize)
|
||||
|
@ -93,7 +93,7 @@ internal class BinaryReader {
|
|||
|
||||
private func readStream(_ buffer: UnsafeMutablePointer<UInt8>, maxLength: Int) throws -> Int {
|
||||
if stream.streamStatus != .open {
|
||||
throw CSVError.cannotReadFile
|
||||
throw CSVError.cannotReadStream
|
||||
}
|
||||
|
||||
var i = 0
|
||||
|
@ -115,7 +115,7 @@ internal class BinaryReader {
|
|||
throw CSVError.streamErrorHasOccurred(error: stream.streamError!)
|
||||
}
|
||||
if length != bufferSize {
|
||||
throw CSVError.cannotReadFile
|
||||
throw CSVError.cannotReadStream
|
||||
}
|
||||
return buffer[0]
|
||||
}
|
||||
|
|
|
@ -10,9 +10,11 @@
|
|||
public enum CSVError: Error {
|
||||
|
||||
/// No overview available.
|
||||
case cannotOpenFile
|
||||
case cannotOpenStream
|
||||
/// No overview available.
|
||||
case cannotReadFile
|
||||
case cannotReadStream
|
||||
/// No overview available.
|
||||
case cannotWriteStream
|
||||
/// No overview available.
|
||||
case streamErrorHasOccurred(error: Error)
|
||||
/// No overview available.
|
||||
|
|
|
@ -24,7 +24,7 @@ public class CSVWriter {
|
|||
|
||||
public let stream: OutputStream
|
||||
public let configuration: Configuration
|
||||
fileprivate let writeScalar: ((UnicodeScalar) -> Void)
|
||||
fileprivate let writeScalar: ((UnicodeScalar) throws -> Void)
|
||||
|
||||
fileprivate var isFirstRecord: Bool = true
|
||||
fileprivate var isFirstField: Bool = true
|
||||
|
@ -32,7 +32,7 @@ public class CSVWriter {
|
|||
fileprivate init(
|
||||
stream: OutputStream,
|
||||
configuration: Configuration,
|
||||
writeScalar: @escaping ((UnicodeScalar) -> Void)) {
|
||||
writeScalar: @escaping ((UnicodeScalar) throws -> Void)) throws {
|
||||
|
||||
self.stream = stream
|
||||
self.configuration = configuration
|
||||
|
@ -41,6 +41,9 @@ public class CSVWriter {
|
|||
if stream.streamStatus == .notOpen {
|
||||
stream.open()
|
||||
}
|
||||
if stream.streamStatus != .open {
|
||||
throw CSVError.cannotOpenStream
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -49,26 +52,29 @@ extension CSVWriter {
|
|||
|
||||
public convenience init(
|
||||
stream: OutputStream,
|
||||
configuration: Configuration = Configuration()) {
|
||||
configuration: Configuration = Configuration()) throws {
|
||||
|
||||
self.init(stream: stream, codecType: UTF8.self, configuration: configuration)
|
||||
try self.init(stream: stream, codecType: UTF8.self, configuration: configuration)
|
||||
}
|
||||
|
||||
public convenience init<T: UnicodeCodec>(
|
||||
stream: OutputStream,
|
||||
codecType: T.Type,
|
||||
configuration: Configuration = Configuration()
|
||||
) where T.CodeUnit == UInt8 {
|
||||
) throws where T.CodeUnit == UInt8 {
|
||||
|
||||
self.init(stream: stream, configuration: configuration) { (scalar: UnicodeScalar) in
|
||||
try self.init(stream: stream, configuration: configuration) { (scalar: UnicodeScalar) throws in
|
||||
var error: CSVError? = nil
|
||||
codecType.encode(scalar) { (code: UInt8) in
|
||||
var code = code
|
||||
let count = stream.write(&code, maxLength: 1)
|
||||
if count != 1 {
|
||||
// FIXME: Error
|
||||
print("ERROR: count != 1")
|
||||
error = CSVError.cannotWriteStream
|
||||
}
|
||||
}
|
||||
if let error = error {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -77,19 +83,22 @@ extension CSVWriter {
|
|||
codecType: T.Type,
|
||||
endian: Endian = .big,
|
||||
configuration: Configuration = Configuration()
|
||||
) where T.CodeUnit == UInt16 {
|
||||
) throws where T.CodeUnit == UInt16 {
|
||||
|
||||
self.init(stream: stream, configuration: configuration) { (scalar: UnicodeScalar) in
|
||||
try self.init(stream: stream, configuration: configuration) { (scalar: UnicodeScalar) throws in
|
||||
var error: CSVError? = nil
|
||||
codecType.encode(scalar) { (code: UInt16) in
|
||||
var code = (endian == .big) ? code.bigEndian : code.littleEndian
|
||||
let count = withUnsafeBytes(of: &code) { (buffer) -> Int in
|
||||
return stream.write(buffer.baseAddress!.assumingMemoryBound(to: UInt8.self), maxLength: buffer.count)
|
||||
}
|
||||
if count != 2 {
|
||||
// FIXME: Error
|
||||
print("ERROR: count != 2")
|
||||
withUnsafeBytes(of: &code) { (buffer) -> Void in
|
||||
let count = stream.write(buffer.baseAddress!.assumingMemoryBound(to: UInt8.self), maxLength: buffer.count)
|
||||
if count != buffer.count {
|
||||
error = CSVError.cannotWriteStream
|
||||
}
|
||||
}
|
||||
}
|
||||
if let error = error {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -98,22 +107,25 @@ extension CSVWriter {
|
|||
codecType: T.Type,
|
||||
endian: Endian = .big,
|
||||
configuration: Configuration = Configuration()
|
||||
) where T.CodeUnit == UInt32 {
|
||||
) throws where T.CodeUnit == UInt32 {
|
||||
|
||||
self.init(stream: stream, configuration: configuration) { (scalar: UnicodeScalar) in
|
||||
try self.init(stream: stream, configuration: configuration) { (scalar: UnicodeScalar) throws in
|
||||
var error: CSVError? = nil
|
||||
codecType.encode(scalar) { (code: UInt32) in
|
||||
var code = (endian == .big) ? code.bigEndian : code.littleEndian
|
||||
let count = withUnsafeBytes(of: &code) { (buffer) -> Int in
|
||||
return stream.write(buffer.baseAddress!.assumingMemoryBound(to: UInt8.self), maxLength: buffer.count)
|
||||
}
|
||||
if count != 4 {
|
||||
// FIXME: Error
|
||||
print("ERROR: count != 4")
|
||||
withUnsafeBytes(of: &code) { (buffer) -> Void in
|
||||
let count = stream.write(buffer.baseAddress!.assumingMemoryBound(to: UInt8.self), maxLength: buffer.count)
|
||||
if count != buffer.count {
|
||||
error = CSVError.cannotWriteStream
|
||||
}
|
||||
}
|
||||
}
|
||||
if let error = error {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
extension CSVWriter {
|
||||
|
@ -122,38 +134,39 @@ extension CSVWriter {
|
|||
isFirstField = true
|
||||
}
|
||||
|
||||
public func write(field value: String, quoted: Bool = false) {
|
||||
public func write(field value: String, quoted: Bool = false) throws {
|
||||
if isFirstRecord {
|
||||
isFirstRecord = false
|
||||
} else {
|
||||
if isFirstField {
|
||||
configuration.newline.unicodeScalars.forEach(writeScalar)
|
||||
try configuration.newline.unicodeScalars.forEach(writeScalar)
|
||||
}
|
||||
}
|
||||
|
||||
if isFirstField {
|
||||
isFirstField = false
|
||||
} else {
|
||||
configuration.delimiter.unicodeScalars.forEach(writeScalar)
|
||||
try configuration.delimiter.unicodeScalars.forEach(writeScalar)
|
||||
}
|
||||
|
||||
var value = value
|
||||
|
||||
if quoted {
|
||||
value = value.replacingOccurrences(of: DQUOTE_STR, with: DQUOTE2_STR)
|
||||
writeScalar(DQUOTE)
|
||||
try writeScalar(DQUOTE)
|
||||
}
|
||||
|
||||
value.unicodeScalars.forEach(writeScalar)
|
||||
try value.unicodeScalars.forEach(writeScalar)
|
||||
|
||||
if quoted {
|
||||
writeScalar(DQUOTE)
|
||||
try writeScalar(DQUOTE)
|
||||
}
|
||||
}
|
||||
|
||||
public func write(row values: [String], quotedAtIndex: ((Int) -> Bool) = { _ in false }) {
|
||||
public func write(record values: [String], quotedAtIndex: ((Int) -> Bool) = { _ in false }) throws {
|
||||
beginNewRecord()
|
||||
for (i, value) in values.enumerated() {
|
||||
write(field: value, quoted: quotedAtIndex(i))
|
||||
try write(field: value, quoted: quotedAtIndex(i))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -38,9 +38,9 @@ class CSVWriterTests: XCTestCase {
|
|||
let stream = OutputStream(toMemory: ())
|
||||
stream.open()
|
||||
|
||||
let csv = CSVWriter(stream: stream)
|
||||
let csv = try! CSVWriter(stream: stream)
|
||||
csv.beginNewRecord()
|
||||
csv.write(field: str)
|
||||
try! csv.write(field: str)
|
||||
|
||||
stream.close()
|
||||
let data = stream.data!
|
||||
|
@ -57,11 +57,11 @@ class CSVWriterTests: XCTestCase {
|
|||
let stream = OutputStream(toMemory: ())
|
||||
stream.open()
|
||||
|
||||
let csv = CSVWriter(stream: stream)
|
||||
let csv = try! CSVWriter(stream: stream)
|
||||
csv.beginNewRecord()
|
||||
csv.write(field: str + "-1")
|
||||
try! csv.write(field: str + "-1")
|
||||
csv.beginNewRecord()
|
||||
csv.write(field: str + "-2")
|
||||
try! csv.write(field: str + "-2")
|
||||
|
||||
stream.close()
|
||||
let data = stream.data!
|
||||
|
@ -77,10 +77,10 @@ class CSVWriterTests: XCTestCase {
|
|||
let stream = OutputStream(toMemory: ())
|
||||
stream.open()
|
||||
|
||||
let csv = CSVWriter(stream: stream)
|
||||
let csv = try! CSVWriter(stream: stream)
|
||||
csv.beginNewRecord()
|
||||
csv.write(field: str + "-1")
|
||||
csv.write(field: str + "-2")
|
||||
try! csv.write(field: str + "-1")
|
||||
try! csv.write(field: str + "-2")
|
||||
|
||||
stream.close()
|
||||
let data = stream.data!
|
||||
|
@ -97,13 +97,13 @@ class CSVWriterTests: XCTestCase {
|
|||
let stream = OutputStream(toMemory: ())
|
||||
stream.open()
|
||||
|
||||
let csv = CSVWriter(stream: stream)
|
||||
let csv = try! CSVWriter(stream: stream)
|
||||
csv.beginNewRecord()
|
||||
csv.write(field: str + "-1-1")
|
||||
csv.write(field: str + "-1-2")
|
||||
try! csv.write(field: str + "-1-1")
|
||||
try! csv.write(field: str + "-1-2")
|
||||
csv.beginNewRecord()
|
||||
csv.write(field: str + "-2-1")
|
||||
csv.write(field: str + "-2-2")
|
||||
try! csv.write(field: str + "-2-1")
|
||||
try! csv.write(field: str + "-2-2")
|
||||
|
||||
stream.close()
|
||||
let data = stream.data!
|
||||
|
@ -119,10 +119,10 @@ class CSVWriterTests: XCTestCase {
|
|||
let stream = OutputStream(toMemory: ())
|
||||
stream.open()
|
||||
|
||||
let csv = CSVWriter(stream: stream)
|
||||
let csv = try! CSVWriter(stream: stream)
|
||||
csv.beginNewRecord()
|
||||
csv.write(field: str + "-1", quoted: true)
|
||||
csv.write(field: str + "-2") // quoted: false
|
||||
try! csv.write(field: str + "-1", quoted: true)
|
||||
try! csv.write(field: str + "-2") // quoted: false
|
||||
|
||||
stream.close()
|
||||
let data = stream.data!
|
||||
|
@ -138,10 +138,10 @@ class CSVWriterTests: XCTestCase {
|
|||
let stream = OutputStream(toMemory: ())
|
||||
stream.open()
|
||||
|
||||
let csv = CSVWriter(stream: stream)
|
||||
let csv = try! CSVWriter(stream: stream)
|
||||
csv.beginNewRecord()
|
||||
csv.write(field: str + "-1") // quoted: false
|
||||
csv.write(field: str + "-\n-2", quoted: true)
|
||||
try! csv.write(field: str + "-1") // quoted: false
|
||||
try! csv.write(field: str + "-\n-2", quoted: true)
|
||||
|
||||
stream.close()
|
||||
let data = stream.data!
|
||||
|
@ -157,10 +157,10 @@ class CSVWriterTests: XCTestCase {
|
|||
let stream = OutputStream(toMemory: ())
|
||||
stream.open()
|
||||
|
||||
let csv = CSVWriter(stream: stream)
|
||||
let csv = try! CSVWriter(stream: stream)
|
||||
csv.beginNewRecord()
|
||||
csv.write(field: str + "-1") // quoted: false
|
||||
csv.write(field: str + "-\"-2", quoted: true)
|
||||
try! csv.write(field: str + "-1") // quoted: false
|
||||
try! csv.write(field: str + "-\"-2", quoted: true)
|
||||
|
||||
stream.close()
|
||||
let data = stream.data!
|
||||
|
|
Loading…
Reference in New Issue