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.
134 lines
5.3 KiB
Swift
134 lines
5.3 KiB
Swift
5 years ago
|
//
|
||
|
// CSV.swift
|
||
|
// SwiftCSV
|
||
|
//
|
||
|
// Created by Naoto Kaneko on 2/18/16.
|
||
|
// Copyright © 2016 Naoto Kaneko. All rights reserved.
|
||
|
//
|
||
|
|
||
|
import Foundation
|
||
|
|
||
|
public protocol View {
|
||
|
associatedtype Rows
|
||
|
associatedtype Columns
|
||
|
|
||
|
var rows: Rows { get }
|
||
|
var columns: Columns { get }
|
||
|
|
||
|
init(header: [String], text: String, delimiter: Character, limitTo: Int?, loadColumns: Bool) throws
|
||
|
}
|
||
|
|
||
|
open class CSV {
|
||
|
static public let comma: Character = ","
|
||
|
|
||
|
public let header: [String]
|
||
|
|
||
|
lazy var _namedView: NamedView = {
|
||
|
return try! NamedView(
|
||
|
header: self.header,
|
||
|
text: self.text,
|
||
|
delimiter: self.delimiter,
|
||
|
loadColumns: self.loadColumns)
|
||
|
}()
|
||
|
|
||
|
lazy var _enumeratedView: EnumeratedView = {
|
||
|
return try! EnumeratedView(
|
||
|
header: self.header,
|
||
|
text: self.text,
|
||
|
delimiter: self.delimiter,
|
||
|
loadColumns: self.loadColumns)
|
||
|
}()
|
||
|
|
||
|
var text: String
|
||
|
var delimiter: Character
|
||
|
|
||
|
let loadColumns: Bool
|
||
|
|
||
|
/// List of dictionaries that contains the CSV data
|
||
|
public var namedRows: [[String : String]] {
|
||
|
return _namedView.rows
|
||
|
}
|
||
|
|
||
|
/// Dictionary of header name to list of values in that column
|
||
|
/// Will not be loaded if loadColumns in init is false
|
||
|
public var namedColumns: [String : [String]] {
|
||
|
return _namedView.columns
|
||
|
}
|
||
|
|
||
|
/// Collection of column fields that contain the CSV data
|
||
|
public var enumeratedRows: [[String]] {
|
||
|
return _enumeratedView.rows
|
||
|
}
|
||
|
|
||
|
/// Collection of columns with metadata.
|
||
|
/// Will not be loaded if loadColumns in init is false
|
||
|
public var enumeratedColumns: [EnumeratedView.Column] {
|
||
|
return _enumeratedView.columns
|
||
|
}
|
||
|
|
||
|
|
||
|
@available(*, unavailable, renamed: "namedRows")
|
||
|
public var rows: [[String : String]] {
|
||
|
return namedRows
|
||
|
}
|
||
|
|
||
|
@available(*, unavailable, renamed: "namedColumns")
|
||
|
public var columns: [String : [String]] {
|
||
|
return namedColumns
|
||
|
}
|
||
|
|
||
|
|
||
|
/// Load CSV data from a string.
|
||
|
///
|
||
|
/// - parameter string: CSV contents to parse.
|
||
|
/// - parameter delimiter: Character used to separate row and header fields (default is ',')
|
||
|
/// - parameter loadColumns: Whether to populate the `columns` dictionary (default is `true`)
|
||
|
/// - throws: `CSVParseError` when parsing `string` fails.
|
||
|
public init(string: String, delimiter: Character = comma, loadColumns: Bool = true) throws {
|
||
|
self.text = string
|
||
|
self.delimiter = delimiter
|
||
|
self.loadColumns = loadColumns
|
||
|
self.header = try Parser.array(text: string, delimiter: delimiter, limitTo: 1).first ?? []
|
||
|
}
|
||
|
|
||
|
@available(*, deprecated, message: "Use init(url:delimiter:encoding:loadColumns:) instead of this path-based approach. Also, calling the parameter `name` instead of `path` was a mistake.")
|
||
|
public convenience init(name: String, delimiter: Character = comma, encoding: String.Encoding = .utf8, loadColumns: Bool = true) throws {
|
||
|
try self.init(url: URL(fileURLWithPath: name), delimiter: delimiter, encoding: encoding, loadColumns: loadColumns)
|
||
|
}
|
||
|
|
||
|
/// Load a CSV file as a named resource from `bundle`.
|
||
|
///
|
||
|
/// - parameter name: Name of the file resource inside `bundle`.
|
||
|
/// - parameter ext: File extension of the resource; use `nil` to load the first file matching the name (default is `nil`)
|
||
|
/// - parameter bundle: `Bundle` to use for resource lookup (default is `.main`)
|
||
|
/// - parameter delimiter: Character used to separate row and header fields (default is ',')
|
||
|
/// - parameter encoding: encoding used to read file (default is `.utf8`)
|
||
|
/// - parameter loadColumns: Whether to populate the columns dictionary (default is `true`)
|
||
|
/// - throws: `CSVParseError` when parsing the contents of the resource fails, or file loading errors.
|
||
|
/// - returns: `nil` if the resource could not be found
|
||
|
public convenience init?(name: String, extension ext: String? = nil, bundle: Bundle = .main, delimiter: Character = comma, encoding: String.Encoding = .utf8, loadColumns: Bool = true) throws {
|
||
|
guard let url = bundle.url(forResource: name, withExtension: ext) else {
|
||
|
return nil
|
||
|
}
|
||
|
try self.init(url: url, delimiter: delimiter, encoding: encoding, loadColumns: loadColumns)
|
||
|
}
|
||
|
|
||
|
/// Load a CSV file from `url`.
|
||
|
///
|
||
|
/// - parameter url: URL of the file (will be passed to `String(contentsOfURL:encoding:)` to load)
|
||
|
/// - parameter delimiter: Character used to separate row and header fields (default is ',')
|
||
|
/// - parameter encoding: Character encoding to read file (default is `.utf8`)
|
||
|
/// - parameter loadColumns: Whether to populate the columns dictionary (default is `true`)
|
||
|
/// - throws: `CSVParseError` when parsing the contents of `url` fails, or file loading errors.
|
||
|
public convenience init(url: URL, delimiter: Character = comma, encoding: String.Encoding = .utf8, loadColumns: Bool = true) throws {
|
||
|
let contents = try String(contentsOf: url, encoding: encoding)
|
||
|
|
||
|
try self.init(string: contents, delimiter: delimiter, loadColumns: loadColumns)
|
||
|
}
|
||
|
|
||
|
/// Turn the CSV data into NSData using a given encoding
|
||
|
open func dataUsingEncoding(_ encoding: String.Encoding) -> Data? {
|
||
|
return description.data(using: encoding)
|
||
|
}
|
||
|
}
|