SwiftはPOSIX APIもわりとそのまま呼べたり、ポインタも( Unsafe とかついているので恐ろしい感じはしますが)かなりいい感じに扱えたりします(cf. Swift - UnsafePointerと上手に付き合う)。
なので、POSIXのAPIだけを使ってファイルを扱うのも簡単です。ことによるとObjective C系のAPIを使うよりも簡単かもしれません。
OSX/iOS系のツールはいままでRubyで書かれることが多かったのですが、POSIX/Foundation/Cocoaをそのまま使えてかつスクリプト言語のように使えるSwiftでコマンドラインツールを書くようになるかもしれないですね。
そいういうわけで、手始めにcat(1)を実装してみました。
#!/usr/bin/xcrun swift
// スクリプト言語のようにshebangを使える!
import Foundation
let files = Process.arguments[1 ..< Process.arguments.count]
// RAIIでfopen()/fclose()するためのラッパークラス
class File {
let fp : UnsafeMutablePointer<FILE>
init(_ filename: String, _ mode: String) {
fp = fopen(filename, mode)
}
deinit {
fclose(fp)
}
}
for file in files {
let f = File(file, "r")
if f.fp == nil {
// string interpolationがあるのでperror()が簡単に使える!
perror("Can't open \(file)")
continue
}
// BUFSIZなどのマクロもある。ただし型変換を明示的にしないといけない
var buf = Array<CChar>(count: Int(BUFSIZ), repeatedValue: 0)
// Int <-> Boolの変換はないのでfoef() -> Intはちょっと面倒
while feof(f.fp) == 0 {
// UIntへの変換が煩雑なことを除くとほぼCそのままで書ける
let nRead = fread(&buf, UInt(sizeof(CChar)), UInt(buf.count), f.fp)
fwrite(&buf, UInt(sizeof(CChar)), nRead, stdout)
}
}
// vim: set tabstop=2 shiftwidth=2: