Implement error handling

This commit is contained in:
Yasuhiro Hatta 2017-05-28 14:27:11 +09:00
parent 1d72634a03
commit eb38710590
4 changed files with 75 additions and 60 deletions

View File

@ -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]
}

View File

@ -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.

View File

@ -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))
}
}

View File

@ -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!