mirror of https://github.com/oxen-io/session-ios
				
				
				
			
			You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			112 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			Swift
		
	
			
		
		
	
	
			112 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			Swift
		
	
//
 | 
						|
//  Parser.swift
 | 
						|
//  SwiftCSV
 | 
						|
//
 | 
						|
//  Created by Will Richardson on 13/04/16.
 | 
						|
//  Copyright © 2016 Naoto Kaneko. All rights reserved.
 | 
						|
//
 | 
						|
 | 
						|
extension CSV {
 | 
						|
    /// Parse the file and call a block on each row, passing it in as a list of fields
 | 
						|
    /// limitTo will limit the result to a certain number of lines
 | 
						|
    public func enumerateAsArray(limitTo: Int? = nil, startAt: Int = 0, _ block: @escaping ([String]) -> ()) throws {
 | 
						|
 | 
						|
        try Parser.enumerateAsArray(text: self.text, delimiter: self.delimiter, limitTo: limitTo, startAt: startAt, block: block)
 | 
						|
    }
 | 
						|
 | 
						|
    public func enumerateAsDict(_ block: @escaping ([String : String]) -> ()) throws {
 | 
						|
 | 
						|
        try Parser.enumerateAsDict(header: self.header, content: self.text, delimiter: self.delimiter, block: block)
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
enum Parser {
 | 
						|
 | 
						|
    static func array(text: String, delimiter: Character, limitTo: Int? = nil, startAt: Int = 0) throws -> [[String]] {
 | 
						|
 | 
						|
        var rows = [[String]]()
 | 
						|
 | 
						|
        try enumerateAsArray(text: text, delimiter: delimiter) { row in
 | 
						|
            rows.append(row)
 | 
						|
        }
 | 
						|
 | 
						|
        return rows
 | 
						|
    }
 | 
						|
 | 
						|
    /// Parse the text and call a block on each row, passing it in as a list of fields.
 | 
						|
    ///
 | 
						|
    /// - parameter text: Text to parse.
 | 
						|
    /// - parameter delimiter: Character to split row and header fields by (default is ',')
 | 
						|
    /// - parameter limitTo: If set to non-nil value, enumeration stops 
 | 
						|
    ///   at the row with index `limitTo` (or on end-of-text, whichever is earlier.
 | 
						|
    /// - parameter startAt: Offset of rows to ignore before invoking `block` for the first time. Default is 0.
 | 
						|
    /// - parameter block: Callback invoked for every parsed row between `startAt` and `limitTo` in `text`.
 | 
						|
    static func enumerateAsArray(text: String, delimiter: Character, limitTo: Int? = nil, startAt: Int = 0, block: @escaping ([String]) -> ()) throws {
 | 
						|
        var currentIndex = text.startIndex
 | 
						|
        let endIndex = text.endIndex
 | 
						|
 | 
						|
        var fields = [String]()
 | 
						|
        var field = ""
 | 
						|
 | 
						|
        var count = 0
 | 
						|
 | 
						|
        func finishRow() {
 | 
						|
            fields.append(String(field))
 | 
						|
            if count >= startAt {
 | 
						|
                block(fields)
 | 
						|
            }
 | 
						|
            count += 1
 | 
						|
            fields = [String]()
 | 
						|
            field = ""
 | 
						|
        }
 | 
						|
 | 
						|
        var state: ParsingState = ParsingState(
 | 
						|
            delimiter: delimiter,
 | 
						|
            finishRow: finishRow,
 | 
						|
            appendChar: { field.append($0) },
 | 
						|
            finishField: {
 | 
						|
                fields.append(field)
 | 
						|
                field = ""
 | 
						|
        })
 | 
						|
 | 
						|
        func limitReached(_ count: Int) -> Bool {
 | 
						|
 | 
						|
            guard let limitTo = limitTo,
 | 
						|
                count >= limitTo
 | 
						|
                else { return false }
 | 
						|
 | 
						|
            return true
 | 
						|
        }
 | 
						|
 | 
						|
        while currentIndex < endIndex {
 | 
						|
            let char = text[currentIndex]
 | 
						|
 | 
						|
            try state.change(char)
 | 
						|
 | 
						|
            if limitReached(count) {
 | 
						|
                break
 | 
						|
            }
 | 
						|
 | 
						|
            currentIndex = text.index(after: currentIndex)
 | 
						|
        }
 | 
						|
 | 
						|
        if !fields.isEmpty || !field.isEmpty || limitReached(count) {
 | 
						|
            fields.append(field)
 | 
						|
            block(fields)
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    static func enumerateAsDict(header: [String], content: String, delimiter: Character, limitTo: Int? = nil, block: @escaping ([String : String]) -> ()) throws {
 | 
						|
 | 
						|
        let enumeratedHeader = header.enumerated()
 | 
						|
 | 
						|
        try enumerateAsArray(text: content, delimiter: delimiter, startAt: 1) { fields in
 | 
						|
            var dict = [String: String]()
 | 
						|
            for (index, head) in enumeratedHeader {
 | 
						|
                dict[head] = index < fields.count ? fields[index] : ""
 | 
						|
            }
 | 
						|
            block(dict)
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 |