Created
September 25, 2014 05:52
-
-
Save burnto/d66494d8523c8a01f624 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
let ScanLines = RegExScanFn("\n|\r|\r\n") | |
let ScanWords = RegExScanFn("\\s") | |
func RegExScanFn(regex : String) -> ((String) -> (String, String?)) { | |
return { (s : String) -> (String, String?) in | |
let ns = s as NSString | |
let location = ns.rangeOfString(regex, options: .RegularExpressionSearch).location | |
if location != NSNotFound { | |
return (ns.substringToIndex(location), ns.substringFromIndex(location + 1)) | |
} else { | |
return (s, nil) | |
} | |
} | |
} | |
class Scanner : SequenceType { | |
var filePath : String | |
var splitFn : (String) -> (String, String?) | |
var bufferSize : Int | |
init(filePath : String, bufferSize : Int = 128, splitFn : (String) -> (String, String?)) { | |
self.filePath = filePath | |
self.bufferSize = bufferSize | |
self.splitFn = splitFn | |
} | |
func generate() -> ScannerGenerator { | |
return ScannerGenerator(filePath: filePath, bufferSize: bufferSize, splitFn) | |
} | |
} | |
class ScannerGenerator : GeneratorType { | |
var stream : NSInputStream | |
var byteBufferSize : Int | |
var byteBuffer : UnsafeMutablePointer<UInt8> | |
var stringBuffer : NSString | |
var splitFn : (String) -> (String, String?) | |
init(filePath : String, bufferSize : Int, splitFn : (String) -> (String, String?)) { | |
self.stream = NSInputStream.inputStreamWithFileAtPath(filePath) | |
self.byteBufferSize = bufferSize + 1 | |
self.splitFn = splitFn | |
byteBuffer = UnsafeMutablePointer<UInt8>.alloc(byteBufferSize) | |
stringBuffer = "" | |
stream.open() | |
} | |
deinit { | |
stream.close() | |
} | |
func next() -> String? { | |
if stream.streamStatus != .Open { | |
return nil | |
} | |
while true { | |
let (s1, s2) : (String, String?) = splitFn(stringBuffer) | |
if (s2 != nil) { | |
stringBuffer = s2! | |
return s1 | |
} | |
var bytesRead = stream.read(byteBuffer, maxLength: byteBufferSize - 1) | |
if bytesRead < 0 { | |
stream.close() | |
return nil | |
} | |
if bytesRead == 0 { | |
break | |
} | |
var charBuffer = UnsafeMutablePointer<CChar>(byteBuffer) | |
charBuffer[bytesRead] = 0 // null terminate the c-string | |
if let utf8String = String.fromCString(charBuffer) { | |
stringBuffer = stringBuffer + utf8String | |
} else { | |
return nil | |
} | |
} | |
stream.close() | |
return stringBuffer | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import XCTest | |
class ScannerTests: XCTestCase { | |
var filePath : String = "" | |
override func setUp() { | |
super.setUp() | |
filePath = NSBundle(forClass: self.dynamicType).pathForResource("TestFile1", ofType: "txt")! | |
} | |
override func tearDown() { | |
super.tearDown() | |
} | |
func testScanLines() { | |
var reader = Scanner(filePath: filePath, splitFn: ScanLines) | |
let g = reader.generate() | |
XCTAssert(g.next() == "Aa") | |
XCTAssert(g.next() == "Bb") | |
XCTAssert(g.next() == "Cc Dd") | |
XCTAssert(g.next() == nil) | |
} | |
func testScanLinesSmallBuffer() { | |
var reader = Scanner(filePath: filePath, bufferSize: 1, splitFn: ScanLines) | |
let g = reader.generate() | |
XCTAssert(g.next() == "Aa") | |
XCTAssert(g.next() == "Bb") | |
XCTAssert(g.next() == "Cc Dd") | |
XCTAssert(g.next() == nil) | |
} | |
func testScanWords() { | |
var reader = Scanner(filePath: filePath, bufferSize: 1, splitFn: ScanWords) | |
let g = reader.generate() | |
XCTAssert(g.next() == "Aa") | |
XCTAssert(g.next() == "Bb") | |
XCTAssert(g.next() == "Cc") | |
XCTAssert(g.next() == "Dd") | |
XCTAssert(g.next() == nil) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment