Skip to content

Instantly share code, notes, and snippets.

@ahknight
Created January 27, 2018 15:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ahknight/d350d4f04a0fb6e3200fd02db8438455 to your computer and use it in GitHub Desktop.
Save ahknight/d350d4f04a0fb6e3200fd02db8438455 to your computer and use it in GitHub Desktop.
Iterates over a large string line-by-line, with configurable line endings. Uses Swift 4's Substring for efficiency.
//
// LineParser.swift
// Mail
//
// Created by Adam Knight on 1/26/18.
//
import Foundation
public class LineParser: Sequence, IteratorProtocol {
public let text: String
private var remaining: Substring
var currentIndex: String.Index
var delimiter: String
public init(_ text: String, delimiter: String = "\r\n") {
self.text = text
self.delimiter = delimiter
remaining = text[text.startIndex..<text.endIndex]
currentIndex = remaining.startIndex
}
public func next() -> Substring? {
let line: Substring
// Find the next delimiter
if let range = remaining.range(of: delimiter, options: .literal) {
// Get the line
line = remaining[remaining.startIndex..<range.lowerBound]
// Update the remaining text
remaining = remaining[range.upperBound..<remaining.endIndex]
// Update the current index.
currentIndex = range.upperBound
return line
}
// Are we done? Use nil as EOF.
if remaining.isEmpty { return nil }
// Return the rest of the string as the last line.
line = remaining
remaining = remaining[remaining.endIndex..<remaining.endIndex]
return line
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment