Add subscript to CSV

This commit is contained in:
Yasuhiro Hatta 2016-06-13 00:21:30 +09:00
parent 7cb02fdc43
commit 484074ade5
5 changed files with 154 additions and 76 deletions

View File

@ -32,6 +32,14 @@
0E7E8D021D0BCDCF0057A1C1 /* CSVVersion.h in Headers */ = {isa = PBXBuildFile; fileRef = 0E7E8C9F1D0BC7F10057A1C1 /* CSVVersion.h */; settings = {ATTRIBUTES = (Public, ); }; };
0E7E8D031D0BCDDD0057A1C1 /* CSVReaderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E7E8CA61D0BC8050057A1C1 /* CSVReaderTests.swift */; };
0E7E8D041D0BCDDD0057A1C1 /* CSVTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E7E8CA71D0BC8050057A1C1 /* CSVTests.swift */; };
0E9317D41D0DB2F200AC20A0 /* CSV+init.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E9317D31D0DB2F200AC20A0 /* CSV+init.swift */; };
0E9317D51D0DB2F200AC20A0 /* CSV+init.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E9317D31D0DB2F200AC20A0 /* CSV+init.swift */; };
0E9317D61D0DB2F200AC20A0 /* CSV+init.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E9317D31D0DB2F200AC20A0 /* CSV+init.swift */; };
0E9317D71D0DB2F200AC20A0 /* CSV+init.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E9317D31D0DB2F200AC20A0 /* CSV+init.swift */; };
0E9317D91D0DB30800AC20A0 /* CSV+subscript.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E9317D81D0DB30800AC20A0 /* CSV+subscript.swift */; };
0E9317DA1D0DB30800AC20A0 /* CSV+subscript.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E9317D81D0DB30800AC20A0 /* CSV+subscript.swift */; };
0E9317DB1D0DB30800AC20A0 /* CSV+subscript.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E9317D81D0DB30800AC20A0 /* CSV+subscript.swift */; };
0E9317DC1D0DB30800AC20A0 /* CSV+subscript.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E9317D81D0DB30800AC20A0 /* CSV+subscript.swift */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@ -74,6 +82,8 @@
0E7E8CCF1D0BCA2A0057A1C1 /* CSVTests-OSX.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "CSVTests-OSX.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
0E7E8CE81D0BCD0B0057A1C1 /* CSV.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = CSV.framework; sourceTree = BUILT_PRODUCTS_DIR; };
0E7E8CF11D0BCD0B0057A1C1 /* CSVTests-tvOS.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "CSVTests-tvOS.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
0E9317D31D0DB2F200AC20A0 /* CSV+init.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CSV+init.swift"; sourceTree = "<group>"; };
0E9317D81D0DB30800AC20A0 /* CSV+subscript.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CSV+subscript.swift"; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -160,6 +170,8 @@
children = (
0E7E8C9C1D0BC7F10057A1C1 /* ByteOrder.swift */,
0E7E8C9D1D0BC7F10057A1C1 /* CSV.swift */,
0E9317D31D0DB2F200AC20A0 /* CSV+init.swift */,
0E9317D81D0DB30800AC20A0 /* CSV+subscript.swift */,
0E7E8C9E1D0BC7F10057A1C1 /* CSVError.swift */,
0E7E8C9F1D0BC7F10057A1C1 /* CSVVersion.h */,
0E7E8CAC1D0BC8610057A1C1 /* Info.plist */,
@ -462,6 +474,8 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
0E9317D51D0DB2F200AC20A0 /* CSV+init.swift in Sources */,
0E9317DA1D0DB30800AC20A0 /* CSV+subscript.swift in Sources */,
0E7E8CA11D0BC7F10057A1C1 /* CSV.swift in Sources */,
0E7E8CA21D0BC7F10057A1C1 /* CSVError.swift in Sources */,
0E7E8CA01D0BC7F10057A1C1 /* ByteOrder.swift in Sources */,
@ -481,6 +495,8 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
0E9317D71D0DB2F200AC20A0 /* CSV+init.swift in Sources */,
0E9317DC1D0DB30800AC20A0 /* CSV+subscript.swift in Sources */,
0E7E8CBE1D0BC9D70057A1C1 /* CSV.swift in Sources */,
0E7E8CBF1D0BC9D70057A1C1 /* CSVError.swift in Sources */,
0E7E8CBD1D0BC9D70057A1C1 /* ByteOrder.swift in Sources */,
@ -491,6 +507,8 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
0E9317D41D0DB2F200AC20A0 /* CSV+init.swift in Sources */,
0E9317D91D0DB30800AC20A0 /* CSV+subscript.swift in Sources */,
0E7E8CE01D0BCA8E0057A1C1 /* CSV.swift in Sources */,
0E7E8CE11D0BCA8E0057A1C1 /* CSVError.swift in Sources */,
0E7E8CDF1D0BCA8E0057A1C1 /* ByteOrder.swift in Sources */,
@ -510,6 +528,8 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
0E9317D61D0DB2F200AC20A0 /* CSV+init.swift in Sources */,
0E9317DB1D0DB30800AC20A0 /* CSV+subscript.swift in Sources */,
0E7E8D001D0BCDCF0057A1C1 /* CSV.swift in Sources */,
0E7E8D011D0BCDCF0057A1C1 /* CSVError.swift in Sources */,
0E7E8CFF1D0BCDCF0057A1C1 /* ByteOrder.swift in Sources */,

70
Sources/CSV+init.swift Normal file
View File

@ -0,0 +1,70 @@
//
// CSV+init.swift
// CSV
//
// Created by Yasuhiro Hatta on 2016/06/13.
// Copyright © 2016 yaslab. All rights reserved.
//
import Foundation
extension CSV {
public convenience init(
path: String,
hasHeaderRow: Bool = defaultHasHeaderRow,
encoding: NSStringEncoding = defaultEncoding,
delimiter: CChar = defaultDelimiter,
bufferSize: Int = defaultBufferSize)
throws
{
guard let stream = NSInputStream(fileAtPath: path) else {
throw CSVError.StreamError
}
try self.init(
stream: stream,
hasHeaderRow: hasHeaderRow,
encoding: encoding,
delimiter: delimiter,
bufferSize: bufferSize)
}
public convenience init(
url: NSURL,
hasHeaderRow: Bool = defaultHasHeaderRow,
encoding: NSStringEncoding = defaultEncoding,
delimiter: CChar = defaultDelimiter,
bufferSize: Int = defaultBufferSize)
throws
{
guard let stream = NSInputStream(URL: url) else {
throw CSVError.StreamError
}
try self.init(
stream: stream,
hasHeaderRow: hasHeaderRow,
encoding: encoding,
delimiter: delimiter,
bufferSize: bufferSize)
}
public convenience init(
string: String,
hasHeaderRow: Bool = defaultHasHeaderRow,
delimiter: CChar = defaultDelimiter,
bufferSize: Int = defaultBufferSize)
throws
{
let encoding = defaultEncoding
guard let data = string.dataUsingEncoding(encoding) else {
throw CSVError.StringEncodingMismatch
}
try self.init(
stream: NSInputStream(data: data),
hasHeaderRow: hasHeaderRow,
encoding: encoding,
delimiter: delimiter,
bufferSize: bufferSize)
}
}

View File

@ -0,0 +1,31 @@
//
// CSV+subscript.swift
// CSV
//
// Created by Yasuhiro Hatta on 2016/06/13.
// Copyright © 2016 yaslab. All rights reserved.
//
import Foundation
extension CSV {
public subscript(key: String) -> String? {
get {
guard let headerRow = headerRow else {
return nil
}
guard let index = headerRow.indexOf(key) else {
return nil
}
guard let currentRow = currentRow else {
return nil
}
if index >= currentRow.count {
return nil
}
return currentRow[index]
}
}
}

View File

@ -40,6 +40,8 @@ public class CSV: SequenceType, GeneratorType {
internal var closed: Bool = false
internal var currentRow: [String]? = nil
/**
CSV header row. To set a value for this property, you set `true` to `hasHeaerRow` in initializer.
*/
@ -169,6 +171,7 @@ public class CSV: SequenceType, GeneratorType {
throw CSVError.HeaderReadError
}
_headerRow = nextRow
currentRow = nil
}
}
@ -194,6 +197,7 @@ public class CSV: SequenceType, GeneratorType {
public func next() -> [String]? {
fieldBuffer.length = 0
currentRow = nil
if closed {
return nil
@ -262,33 +266,30 @@ public class CSV: SequenceType, GeneratorType {
escaping = true
}
if (c == delimiter || c == CR || c == LF) && prev == DQUOTE && (quotationCount % 2 == 0) {
if escaping && prev == DQUOTE && (c == delimiter || c == CR || c == LF) && (quotationCount % 2 == 0) {
escaping = false
}
//
if prev == CR && c != LF && !escaping {
if !escaping && prev == CR && c != LF {
fieldBuffer.appendBytes(buffer + fieldStart, length: charWidth * charLength)
break
}
//
if c == LF && !escaping {
fieldBuffer.appendBytes(buffer + fieldStart, length: charWidth * charLength)
bufferOffset += charWidth
break
}
prev = c
bufferOffset += charWidth
//
if c == CR && !escaping {
continue
if !escaping {
if c == CR {
continue
}
if c == LF {
fieldBuffer.appendBytes(buffer + fieldStart, length: charWidth * charLength)
break
}
}
//
if c == delimiter && !escaping {
if !escaping && c == delimiter {
fieldBuffer.appendBytes(buffer + fieldStart, length: charWidth * charLength)
guard let field = getField(quotationCount) else {
@ -318,6 +319,7 @@ public class CSV: SequenceType, GeneratorType {
}
fields.append(field)
currentRow = fields
return fields
}
@ -356,65 +358,3 @@ public class CSV: SequenceType, GeneratorType {
}
}
extension CSV {
public convenience init(
path: String,
hasHeaderRow: Bool = defaultHasHeaderRow,
encoding: NSStringEncoding = defaultEncoding,
delimiter: CChar = defaultDelimiter,
bufferSize: Int = defaultBufferSize)
throws
{
guard let stream = NSInputStream(fileAtPath: path) else {
throw CSVError.StreamError
}
try self.init(
stream: stream,
hasHeaderRow: hasHeaderRow,
encoding: encoding,
delimiter: delimiter,
bufferSize: bufferSize)
}
public convenience init(
url: NSURL,
hasHeaderRow: Bool = defaultHasHeaderRow,
encoding: NSStringEncoding = defaultEncoding,
delimiter: CChar = defaultDelimiter,
bufferSize: Int = defaultBufferSize)
throws
{
guard let stream = NSInputStream(URL: url) else {
throw CSVError.StreamError
}
try self.init(
stream: stream,
hasHeaderRow: hasHeaderRow,
encoding: encoding,
delimiter: delimiter,
bufferSize: bufferSize)
}
public convenience init(
string: String,
hasHeaderRow: Bool = defaultHasHeaderRow,
delimiter: CChar = defaultDelimiter,
bufferSize: Int = defaultBufferSize)
throws
{
let encoding = defaultEncoding
guard let data = string.dataUsingEncoding(encoding) else {
throw CSVError.StringEncodingMismatch
}
let memoryStream = NSInputStream(data: data)
try self.init(
stream: memoryStream,
hasHeaderRow: hasHeaderRow,
encoding: encoding,
delimiter: delimiter,
bufferSize: bufferSize)
}
}

View File

@ -128,4 +128,21 @@ class CSVTests: XCTestCase {
XCTAssertEqual(i, 10000)
}
func testSubscript() {
let csvString = "id,name\n001,hoge\n002,fuga"
let csv = try! CSV(string: csvString, hasHeaderRow: true)
var table = [[String]]()
while csv.next() != nil {
var row = [String]()
row.append(csv["id"]!)
row.append(csv["name"]!)
table.append(row)
}
XCTAssertEqual(table.count, 2)
XCTAssertEqual(table[0][0], "001")
XCTAssertEqual(table[0][1], "hoge")
XCTAssertEqual(table[1][0], "002")
XCTAssertEqual(table[1][1], "fuga")
}
}