Add buffer size tests
This commit is contained in:
parent
e3842e3db7
commit
bec2704832
|
@ -25,23 +25,30 @@ internal let utf32LittleEndianBOM: [UInt8] = [0xff, 0xfe, 0x00, 0x00]
|
||||||
|
|
||||||
public class CSV: SequenceType, GeneratorType {
|
public class CSV: SequenceType, GeneratorType {
|
||||||
|
|
||||||
private let stream: NSInputStream
|
internal let stream: NSInputStream
|
||||||
private let encoding: NSStringEncoding
|
internal let encoding: NSStringEncoding
|
||||||
private let delimiter: UInt32
|
internal let delimiter: UInt32
|
||||||
private let bufferSize: Int
|
internal let bufferSize: Int
|
||||||
|
|
||||||
private var buffer: UnsafeMutablePointer<UInt8>!
|
internal var buffer: UnsafeMutablePointer<UInt8>!
|
||||||
private var bufferOffset: Int
|
internal var bufferOffset: Int
|
||||||
private var lastReadCount: Int
|
internal var lastReadCount: Int
|
||||||
|
|
||||||
private let charWidth: Int
|
internal let charWidth: Int
|
||||||
|
|
||||||
private let fieldBuffer: NSMutableData
|
internal let fieldBuffer: NSMutableData
|
||||||
|
|
||||||
|
internal var closed: Bool = false
|
||||||
|
|
||||||
|
/**
|
||||||
|
CSV header row. To set a value for this property, you set `true` to `hasHeaerRow` in initializer.
|
||||||
|
*/
|
||||||
|
public var headerRow: [String]? { return _headerRow }
|
||||||
private var _headerRow: [String]? = nil
|
private var _headerRow: [String]? = nil
|
||||||
|
|
||||||
private var closed: Bool = false
|
/**
|
||||||
|
The value is set when an error occurs.
|
||||||
/** The value is set when an error occurs. */
|
*/
|
||||||
public private(set) var lastError: CSVError? = nil
|
public private(set) var lastError: CSVError? = nil
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -70,7 +77,11 @@ public class CSV: SequenceType, GeneratorType {
|
||||||
if bs < 8 {
|
if bs < 8 {
|
||||||
bs = 8
|
bs = 8
|
||||||
}
|
}
|
||||||
self.bufferSize = bs + (4 - (bs % 4))
|
let mod = bs % 4
|
||||||
|
if mod != 0 {
|
||||||
|
bs += 4 - mod
|
||||||
|
}
|
||||||
|
self.bufferSize = bs
|
||||||
|
|
||||||
self.delimiter = UInt32(delimiter)
|
self.delimiter = UInt32(delimiter)
|
||||||
|
|
||||||
|
@ -175,18 +186,10 @@ public class CSV: SequenceType, GeneratorType {
|
||||||
free(buffer)
|
free(buffer)
|
||||||
buffer = nil
|
buffer = nil
|
||||||
}
|
}
|
||||||
_headerRow = nil
|
|
||||||
closed = true
|
closed = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
CSV header row. To set a value for this property, you set `true` to `hasHeaerRow` in initializer.
|
|
||||||
*/
|
|
||||||
public var headerRow: [String]? {
|
|
||||||
return _headerRow
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: GeneratorType
|
// MARK: GeneratorType
|
||||||
|
|
||||||
public func next() -> [String]? {
|
public func next() -> [String]? {
|
||||||
|
@ -259,11 +262,7 @@ public class CSV: SequenceType, GeneratorType {
|
||||||
escaping = true
|
escaping = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if c == delimiter && prev == DQUOTE && (quotationCount % 2 == 0) {
|
if (c == delimiter || c == CR || c == LF) && prev == DQUOTE && (quotationCount % 2 == 0) {
|
||||||
escaping = false
|
|
||||||
}
|
|
||||||
|
|
||||||
if (c == CR || c == LF) && prev == DQUOTE && (quotationCount % 2 == 0) {
|
|
||||||
escaping = false
|
escaping = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -365,30 +364,46 @@ extension CSV {
|
||||||
public convenience init(
|
public convenience init(
|
||||||
path: String,
|
path: String,
|
||||||
hasHeaderRow: Bool = defaultHasHeaderRow,
|
hasHeaderRow: Bool = defaultHasHeaderRow,
|
||||||
encoding: NSStringEncoding = defaultEncoding)
|
encoding: NSStringEncoding = defaultEncoding,
|
||||||
|
delimiter: CChar = defaultDelimiter,
|
||||||
|
bufferSize: Int = defaultBufferSize)
|
||||||
throws
|
throws
|
||||||
{
|
{
|
||||||
guard let stream = NSInputStream(fileAtPath: path) else {
|
guard let stream = NSInputStream(fileAtPath: path) else {
|
||||||
throw CSVError.StreamError
|
throw CSVError.StreamError
|
||||||
}
|
}
|
||||||
try self.init(stream: stream, hasHeaderRow: hasHeaderRow, encoding: encoding)
|
try self.init(
|
||||||
|
stream: stream,
|
||||||
|
hasHeaderRow: hasHeaderRow,
|
||||||
|
encoding: encoding,
|
||||||
|
delimiter: delimiter,
|
||||||
|
bufferSize: bufferSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
public convenience init(
|
public convenience init(
|
||||||
url: NSURL,
|
url: NSURL,
|
||||||
hasHeaderRow: Bool = defaultHasHeaderRow,
|
hasHeaderRow: Bool = defaultHasHeaderRow,
|
||||||
encoding: NSStringEncoding = defaultEncoding)
|
encoding: NSStringEncoding = defaultEncoding,
|
||||||
|
delimiter: CChar = defaultDelimiter,
|
||||||
|
bufferSize: Int = defaultBufferSize)
|
||||||
throws
|
throws
|
||||||
{
|
{
|
||||||
guard let stream = NSInputStream(URL: url) else {
|
guard let stream = NSInputStream(URL: url) else {
|
||||||
throw CSVError.StreamError
|
throw CSVError.StreamError
|
||||||
}
|
}
|
||||||
try self.init(stream: stream, hasHeaderRow: hasHeaderRow, encoding: encoding)
|
try self.init(
|
||||||
|
stream: stream,
|
||||||
|
hasHeaderRow: hasHeaderRow,
|
||||||
|
encoding: encoding,
|
||||||
|
delimiter: delimiter,
|
||||||
|
bufferSize: bufferSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
public convenience init(
|
public convenience init(
|
||||||
string: String,
|
string: String,
|
||||||
hasHeaderRow: Bool = defaultHasHeaderRow)
|
hasHeaderRow: Bool = defaultHasHeaderRow,
|
||||||
|
delimiter: CChar = defaultDelimiter,
|
||||||
|
bufferSize: Int = defaultBufferSize)
|
||||||
throws
|
throws
|
||||||
{
|
{
|
||||||
let encoding = defaultEncoding
|
let encoding = defaultEncoding
|
||||||
|
@ -396,7 +411,12 @@ extension CSV {
|
||||||
throw CSVError.StringEncodingMismatch
|
throw CSVError.StringEncodingMismatch
|
||||||
}
|
}
|
||||||
let memoryStream = NSInputStream(data: data)
|
let memoryStream = NSInputStream(data: data)
|
||||||
try self.init(stream: memoryStream, hasHeaderRow: hasHeaderRow, encoding: encoding)
|
try self.init(
|
||||||
|
stream: memoryStream,
|
||||||
|
hasHeaderRow: hasHeaderRow,
|
||||||
|
encoding: encoding,
|
||||||
|
delimiter: delimiter,
|
||||||
|
bufferSize: bufferSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,4 +84,48 @@ class CSVTests: XCTestCase {
|
||||||
XCTAssertEqual(i, 3)
|
XCTAssertEqual(i, 3)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testBufferSizeMod0() {
|
||||||
|
let csvString = "0,1,2,3,4,5,6,7,8,9\n"
|
||||||
|
let csv = try! CSV(string: csvString, bufferSize: 12)
|
||||||
|
XCTAssertEqual(csv.bufferSize, 12)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testBufferSizeMod1() {
|
||||||
|
let csvString = "0,1,2,3,4,5,6,7,8,9\n"
|
||||||
|
let csv = try! CSV(string: csvString, bufferSize: 13)
|
||||||
|
XCTAssertEqual(csv.bufferSize, 16)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testBufferSizeMod2() {
|
||||||
|
let csvString = "0,1,2,3,4,5,6,7,8,9\n"
|
||||||
|
let csv = try! CSV(string: csvString, bufferSize: 14)
|
||||||
|
XCTAssertEqual(csv.bufferSize, 16)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testBufferSizeMod3() {
|
||||||
|
let csvString = "0,1,2,3,4,5,6,7,8,9\n"
|
||||||
|
let csv = try! CSV(string: csvString, bufferSize: 15)
|
||||||
|
XCTAssertEqual(csv.bufferSize, 16)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testBufferSizeMod4() {
|
||||||
|
let csvString = "0,1,2,3,4,5,6,7,8,9\n"
|
||||||
|
let csv = try! CSV(string: csvString, bufferSize: 16)
|
||||||
|
XCTAssertEqual(csv.bufferSize, 16)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testSmallBufferSize() {
|
||||||
|
let line = "0,1,2,3,4,5,6,7,8,9\n"
|
||||||
|
var csv = ""
|
||||||
|
for _ in 0..<10000 {
|
||||||
|
csv += line
|
||||||
|
}
|
||||||
|
var i = 0
|
||||||
|
for row in try! CSV(string: csv, bufferSize: 10) {
|
||||||
|
XCTAssertEqual(row, ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"])
|
||||||
|
i += 1
|
||||||
|
}
|
||||||
|
XCTAssertEqual(i, 10000)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue