LoginSignup
25
25

More than 5 years have passed since last update.

SwiftのPOSIX APIでcat(1)を書く

Last updated at Posted at 2014-08-06

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:
25
25
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
25
25