/* Serval DNA Swift CLI output Copyright 2017 Flinders University This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import Foundation import servald.cli private extension Data { var hexUpper: String { return map { String(format: "%02hhX", $0) }.joined() } } open class CliContext { public var cContext: cli_context = cli_context(context: nil, vtable: nil) public init() { cContext.context = UnsafeMutableRawPointer(Unmanaged.passUnretained(self).toOpaque()) cContext.vtable = UnsafeMutablePointer(&cliVtable) } // Subclasses override these as needed: func delim(_ opt: String? = nil) {} func write(_ data: Data) {} func puts(_ str: String) { self.write(str.data(using:.utf8)!) } func flush() {} func putString(_ str: String, _ delim: String? = nil) { self.puts(str) self.delim(delim) } func putLong(_ value: Int64, _ delim: String? = nil) { self.puts("\(value)") self.delim(delim) } func putHexData(_ data: Data, _ delim: String? = nil) { self.puts(data.hexUpper) self.delim(delim) } func putBlob(_ data: Data, _ delim: String? = nil) { self.write(data) self.delim(delim) } func startTable(column_names: [String]) { self.putLong(Int64(column_names.count)) for i in 0 ..< column_names.count { self.putString(column_names[i], i == column_names.count - 1 ? nil : ":") } } func endTable(row_count: Int) {} func fieldName(_ name: String, _ delim: String? = nil) { self.putString(name) self.delim(delim) } } private func _self(_ context: UnsafeMutablePointer?) -> CliContext { return Unmanaged.fromOpaque(context!.pointee.context).takeUnretainedValue() } private func cliDelim(_ context: UnsafeMutablePointer?, _ opt: UnsafePointer?) -> Void { _self(context).delim(opt != nil ? String(cString: opt!) : nil) } private func cliWrite(_ context: UnsafeMutablePointer?, _ buf: UnsafePointer?, _ len: Int) -> Void { if buf != nil { _self(context).write(Data(bytes: buf!, count: len)) } } private func cliPuts(_ context: UnsafeMutablePointer?, _ str: UnsafePointer?) -> Void { if str != nil { _self(context).putString(String(cString: str!)) } } private func cliVprintf(_ context: UnsafeMutablePointer?, _ fmt: UnsafePointer?, _ ap: CVaListPointer) -> Void { let str = NSString(format: String(cString: fmt!), arguments: ap) _self(context).putString(String(data: str.data(using: String.Encoding.utf16.rawValue)!, encoding:.utf16)!) } private func cliPutLong(_ context: UnsafeMutablePointer?, _ value: Int64, _ delim: UnsafePointer?) -> Void { _self(context).putLong(value, delim != nil ? String(cString: delim!) : nil) } private func cliPutString(_ context: UnsafeMutablePointer?, _ value: UnsafePointer?, _ delim: UnsafePointer?) -> Void { _self(context).putString(value != nil ? String(cString: value!) : "", delim != nil ? String(cString: delim!) : nil) } private func cliPutHexvalue(_ context: UnsafeMutablePointer?, _ buf: UnsafePointer?, _ len: Int, _ delim: UnsafePointer?) -> Void { _self(context).putHexData(buf != nil ? Data(bytes: buf!, count: len) : Data(), delim != nil ? String(cString: delim!) : nil) } private func cliPutBlob(_ context: UnsafeMutablePointer?, _ blob: UnsafePointer?, _ len: Int, _ delim: UnsafePointer?) -> Void { _self(context).putBlob(blob != nil ? Data(bytes: UnsafeRawPointer(blob!).bindMemory(to: CChar.self, capacity: len), count: len) : Data(), delim != nil ? String(cString: delim!) : nil) } private func cliStartTable(_ context: UnsafeMutablePointer?, _ column_count: Int, _ column_names: UnsafeMutablePointer?>?) -> Void { let names = (0..?, _ row_count: Int) -> Void { _self(context).endTable(row_count: row_count) } private func cliFieldName(_ context: UnsafeMutablePointer?, _ name: UnsafePointer?, _ delim: UnsafePointer?) -> Void { _self(context).fieldName(name != nil ? String(cString: name!) : "", delim != nil ? String(cString: delim!) : nil) } private func cliFlush(_ context: UnsafeMutablePointer?) -> Void { _self(context).flush() } private var cliVtable = cli_vtable( delim: cliDelim, write: cliWrite, puts: cliPuts, vprintf: cliVprintf, put_long: cliPutLong, put_string: cliPutString, put_hexvalue: cliPutHexvalue, put_blob: cliPutBlob, start_table: cliStartTable, end_table: cliEndTable, field_name: cliFieldName, flush: cliFlush )