6.55. kink/io/INPUT

input 型のコンパニオンモジュール。

6.55.1. input 型

input はファイルなど下層にあるソースからのバイト列の入力ポートである。

input は下層にあるソースへのシーケンシャルなアクセスを提供する。シークなどのランダムアクセス操作は提供しない。

6.55.1.1. Input.read(Max_size ...[$config={}])

read はストリームからバイト列を読み込む。 read は最低1バイトが読まれるか、end-of-fileが検出されるか、IOエラーが発生するまでブロックする。

コンフィグメソッド:

• C.on_success($success): default = VAL.identity

• C.on_eof($eof): default = 例外を投げる関数

• C.on_error($error): default = 例外を投げる関数

1バイト以上が読み込まれた場合、 read は$successに読み込まれた bin を渡して末尾呼び出しする。 bin の長さは Max_size を超えない。

end-of-fileが検出された場合、 read は$eofを引数なしで末尾呼び出しする。

IOエラーが起きた場合、 read は$errorに exception を渡して末尾呼び出しする。

事前条件

Max_size は1以上の整数の num 値でなければならない。

$successは bin を取る関数でなければならない。

$eofは引数を取らない関数でなければならない。

$errorは exception を取る関数でなければならない。

:BIN.require_from('kink/')
:BIN_INPUT.require_from('kink/io/')

:In <- BIN_INPUT.new(BIN.of(1 2 3))
:loop <- {(:Vec)
  In.read(2){(:C)
    C.on_success{(:Bin) loop(Vec + [Bin]) }
    C.on_eof{ Vec }
  }
}
:Result <- loop([])
stdout.print_line(Result.repr)  # => [(bin 0x01 0x02) (bin 0x03)]

例: IOエラー

:FILE.require_from('kink/io/')
:CONTROL.require_from('kink/')

:In <- FILE.open_to_read('/etc/passwd')
In.close
In.read(10){(:C)
  C.on_error{(:Exc)
    stderr.print_line(Exc.message)
  }
}
# => already closed

In.read(10)
# Output:
#   -- main exception
#   [..root..]
#   {..call by host..}
#   ,,,
#   {builtin:kink-mods/kink/EXCEPTION.kn L117 C13 current_traces} { TRACE.-->current_traces }
#   already closed

6.55.1.2. Input.read_all(...[$config={}])

read_all はend-of-fileに達するか、IOエラーが起きるまでバイト列を読み込む。

コンフィグメソッド:

• C.on_success($success): default = VAL.identity

• C.on_error($error): default = {(:Exc) Exc.raise }

IOエラーなしに1バイト以上読み込まれた場合、 read_all は$successを bin を渡して末尾呼び出しする。

1バイトも読み込まれなかった場合、 read_all は$successを、空の bin を渡して末尾呼び出しする。

IOエラーが起きた場合、 read_all は$errorを、 exception を渡して末尾呼び出しする。

事前条件

$successは bin を取る関数でなければならない。

$errorは exception を取る関数でなければならない。

:BIN.require_from('kink/')
:BIN_INPUT.require_from('kink/io/')
:INPUT.require_from('kink/io/')

:In <- BIN_INPUT.new(BIN.of(1 2 3))
stdout.print_line(In.read_all.repr)  # => (bin 0x01 0x02 0x03)
stdout.print_line(In.read_all.repr)  # => (bin)
stdout.print_line(In.read_all.repr)  # => (bin)

参照

INPUT.mixin: read_all の一般的な実装を提供している。

6.55.1.3. Input.close(...[$config={}])

close はバイト列のソースであるリソースを閉じる。

コンフィグメソッド:

• C.on_success($success): default = {}

• C.on_error($error): default = 例外を投げる関数

リソースがエラーなしに閉じられた場合、 close は$successを引数なしで末尾呼び出しする。

IOエラーが起きた場合、 close は$errorを exception を渡して末尾呼び出しする。

事前条件

$successは引数を取らない関数でなければならない。

$errorは exception を取る関数でなければならない。

6.55.2. INPUT.is?(Val)

is? は Val が input かどうかを戻す。

6.55.3. INPUT.mixin

mixin はInput.read_allの実装を提供するミックスイントレイトを戻す。 read_all は read メソッドを用いて実装される。

:CONTROL.require_from('kink/')
:INPUT.require_from('kink/io/')
:FILE.require_from('kink/io/')

:Trait <- [
  ... INPUT.mixin

  'read' {[:In](:Args.rest)
    stderr.print_line('Called: read')
    In.Wrapped.read(... Args)
  }

  'close' {[:In](:Args.rest)
    stderr.print_line('Called: close')
    In.Wrapped.close(... Args)
  }
]

:new_logging_input <- {(:Wrapped)
  new_val(
    ... Trait
    'Wrapped' Wrapped
  )
}

:main <- {
  :Bin = CONTROL.with_finally{(:finally)
    :In = new_logging_input(FILE.open_to_read('/etc/passwd'))
    finally{ In.close }
    In.read_all
  }
  stdout.write(Bin)
}
# Output:
#   Called: read
#   Called: read
#   Called: close
#   root:x:0:0:root:/root:/bin/bash
#   daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
#   bin:x:2:2:bin:/bin:/usr/sbin/nologin
#   sys:x:3:3:sys:/dev:/usr/sbin/nologin
#   ,,,