The IMPERATIVE_IO 시그니처
The IMPERATIVE_IO 시그니처
IMPERATIVE_IO 시그니처는 I/O 스택에서 명령형 I/O 계층의 인터페이스를 정의해요. 이 계층은 가변·재지정 가능한 스트림을 사용하는 버퍼링된 I/O를 제공해요.
출처: 문서
본문
시놉시스 (Synopsis)
signature IMPERATIVE_IO
인터페이스 (Interface)
structure StreamIO : STREAM_IO
type vector = StreamIO.vector
type elem = StreamIO.elem
type instream
type outstream
val input : instream -> vector
val input1 : instream -> elem option
val inputN : instream * int -> vector
val inputAll : instream -> vector
val canInput : instream * int -> int option
val lookahead : instream -> elem option
val closeIn : instream -> unit
val endOfStream : instream -> bool
val output : outstream * vector -> unit
val output1 : outstream * elem -> unit
val flushOut : outstream -> unit
val closeOut : outstream -> unit
val mkInstream : StreamIO.instream -> instream
val getInstream : instream -> StreamIO.instream
val setInstream : instream * StreamIO.instream -> unit
val mkOutstream : StreamIO.outstream -> outstream
val getOutstream : outstream -> StreamIO.outstream
val setOutstream : outstream * StreamIO.outstream -> unit
val getPosOut : outstream -> StreamIO.out_pos
val setPosOut : outstream * StreamIO.out_pos -> unit
설명 (Description)
structure StreamIO : STREAM_IO
이 하위 구조는 STREAM_IO 인터페이스가 정의하는 더 낮은 수준의 스트림 I/O를 제공해요. 이는 mkInstream, getInstream, mkOutstream, getOutstream 변환 함수가 저수준 스트림과 재지정 가능한 스트림 사이를 변환하게 해준다는 점에서 instream·outstream 타입과 호환돼요. 보통 재지정 가능한 스트림은 저수준 스트림으로 구현돼요. StreamIO.outstream은 함수형 스트림이 아니라는 점에 주의해요. StreamIO.outstream과 outstream의 유일한 차이는 후자가 재지정될 수 있다는 것이에요.
type vector = StreamIO.vector
type elem = StreamIO.elem
스트림 요소와 요소 벡터의 추상 타입이에요. 텍스트 스트림에서는 Char.char와 String.string이고, 이진 스트림에서는 Word8.word와 Word8Vector.vector에 해당해요.
type instream
재지정 가능한 명령형 입력 스트림의 타입이에요. 두 명령형 스트림이 밑에 깔린 함수형 스트림이나 리더를 공유할 수 있어요. 둘 중 하나를 닫으면 효과적으로 밑에 깔린 함수형 스트림을 닫게 되어, 다른 쪽의 후속 연산에 영향을 줘요.
type outstream
재지정 가능한 출력 스트림의 타입이에요. 두 재지정 가능한 스트림이 밑에 깔린 스트림이나 라이터를 공유할 수 있어요. 그렇다면 하나에 쓰거나 파일 포인터를 위치시키거나 닫는 일이 다른 쪽에도 영향을 줘요.
input strm
현재 입력 파일 위치에서 strm 읽기를 시도해요. 요소를 사용할 수 있으면 최소한 한 요소의 벡터를 돌려줘요. strm이 스트림 끝이거나 닫혀 있으면 빈 벡터를 돌려줘요. 그 외에는 이 조건 중 하나가 충족될 때까지 입력을 차단하고 그에 맞게 돌려줘요. Io 예외를 발생시킬 수 있어요.
input1 strm
strm에서 한 요소를 읽어요. 요소가 하나 있었다면 SOME(e)를, 스트림 끝이면 NONE을 돌려줘요. 차단할 수 있고 Io 예외를 발생시킬 수 있어요. end-of-stream을 나타내는 NONE을 돌려주는 input1 호출 후에는 입력 스트림이 end-of-stream 뒤에 위치해야 해요.
inputN (strm, n)
strm에서 최대 n개의 요소를 읽어요. end-of-stream 전에 최소 n개 요소를 사용할 수 있으면 n개 요소를 담은 벡터를 돌려주고, 아니면 end-of-stream 전에 남은 모든 요소의 더 짧은(그리고 아마 빈) 벡터를 돌려줘요. 차단할 수 있고 Io 예외를 발생시킬 수 있어요. n < 0이거나 n이 벡터 타입의 maxLen보다 크면 Size를 발생시켜요.
inputAll strm
end-of-stream까지 strm의 모든 요소를 돌려줘요. 차단할 수 있고 Io 예외를 발생시킬 수 있어요. 데이터 양이 벡터 타입의 maxLen을 초과하면 Size를 발생시켜요.
canInput (strm, n)
입력 시도가 차단되면 NONE을 돌려줘요. input 호출이 최소 k개의 문자와 함께 즉시 돌아온다면 SOME(k)(0 <= k <= n)을 돌려줘요. k = 0은 스트림이 end-of-stream에 있음을 뜻해요. 일부 스트림은 이 연산을 지원하지 않아 Io 예외가 발생할 수 있어요. 밑에 깔린 시스템 호출에 오류가 있어도 Io 예외를 발생시켜요. n < 0이면 Size 예외를 발생시켜요. 구현 참고: canInput 구현은 가능한 한 큰 k를 돌려주도록 노력하는 것이 좋아요. 예를 들어 버퍼에 10문자가 있고 사용자가 canInput (f, 15)를 호출하면, canInput은 추가 5문자를 확인하려고 readVecNB(5)를 호출해야 해요.
lookahead strm
strm에 end-of-stream 전에 요소 하나가 사용 가능한지 결정하고 그 경우 SOME(e)를 돌려줘요. end-of-stream이면 NONE을 돌려줘요. 전자의 경우 e는 strm에서 제거되지 않고 추가 입력 연산에 계속 사용 가능해요. 차단할 수 있고 Io 예외를 발생시킬 수 있어요. 밑에 깔린 STREAM_IO 스트림으로 임의의 lookahead를 쉽게 구현할 수 있어요.
closeIn strm
입력 스트림 strm을 닫고 그와 연관된 밑에 깔린 I/O 계층의 자원을 해제해요. 이미 닫힌 스트림을 닫는 것은 무시돼요. 닫힌 스트림의 다른 연산은 스트림이 end-of-stream에 있는 것처럼 동작해요. 이 함수는 StreamIO.closeIn으로 구현돼요. 다른 오류가 발생하면 Io도 발생시킬 수 있어요.
endOfStream strm
strm이 end-of-stream이면 true, 요소가 아직 있으면 false를 돌려줘요. 이 조건 중 하나가 결정될 때까지 차단할 수 있고 Io 예외를 발생시킬 수 있어요. 자르지 않은 스트림에서 endOfStream이 true를 돌려줄 때 이는 현재 상황을 나타내요. end-of-stream을 소비하는 strm 읽기 후에는 다음 endOfStream strm 호출이 false를 돌려주고 입력 연산이 새 요소를 전달할 수 있어요. 자세한 내용은 STREAM_IO.endOfStream 설명을 보세요.
output (strm, vec)
vec의 내용을 현재 출력 파일 위치에서 strm에 쓰려고 시도해요. 밑에 깔린 계층(그리고 결국 운영체제)이 vec 전체를 받아들일 수 있을 때까지 차단할 수 있어요. Io 예외를 발생시킬 수 있어요. 그 경우 vec 중 실제로 얼마나 쓰였는지는 명시되지 않아요.
output1 (strm, el)
정확히 한 요소 el을 strm에 써요. 차단할 수 있고 오류가 발생하면 Io 예외를 발생시킬 수 있어요. 그 경우 el 중 실제로 얼마나 쓰였는지는, 특히 물리적 표현이 한 바이트보다 크면, 명시되지 않아요. 이 수준에서는 이보다 더 보장할 수 없어요. 이 가능성을 더 제어해야 하는 프로그램은 더 원시적이거나 OS 특정적인 I/O 루틴을 사용해야 해요.
flushOut strm
strm에 연관된 버퍼를 모두 기록하게 해요. StreamIO.flushOut으로 구현돼요. 차단할 수 있고 오류 발생 시 Io 예외를 발생시킬 수 있어요.
closeOut strm
strm에 연관된 버퍼를 플러시한 다음 strm을 닫아 밑에 깔린 I/O 계층의 자원을 해제해요. StreamIO.closeOut으로 구현돼요. 닫힌 outstream에 쓰려 하면 Io{cause=ClosedStream,...} 예외가 발생해요. 다른 오류(예: 버퍼를 플러시할 수 없음)가 있어도 Io를 발생시킬 수 있어요.
mkInstream strm
함수형 스트림에서 재지정 가능한 입력 스트림을 구성해요. 입력 연산이 돌려주는 현재 버전의 strm이 내부에 유지되어 다음 입력에 사용돼요. getInstream으로 얻을 수 있어요.
getInstream strm
strm의 밑에 깔린 함수형 입력 스트림의 현재 버전을 돌려줘요. getInstream을 사용하면 밑에 깔린 함수형 스트림에서 직접 입력을 얻을 수 있어요. 그렇게 한 뒤에는 새로 얻은 함수형 스트림을 setInstream으로 strm에 다시 할당해야 할 수도 있어요. 그렇지 않으면 다음에 strm에서 읽을 때 이전 입력을 다시 읽게 돼요.
setInstream (strm, strm')
새 함수형 스트림 strm'을 strm에 할당해요. 앞으로 strm에서의 입력은 strm'에서 읽혀요. 입력을 재지정하거나 다른 스트림의 입력을 번갈아 읽을 때(예: 렉서에서 중첩 include 파일 처리) 유용해요.
mkOutstream strm
저수준 함수형 스트림에서 재지정 가능한 출력 스트림을 구성해요. 명령형 스트림으로의 출력은 strm으로 재지정돼요.
getOutstream strm
strm을 플러시하고 밑에 깔린 StreamIO 출력 스트림을 돌려줘요. getOutstream을 사용하면 밑에 깔린 스트림에 직접 출력하거나, strm이 재지정된 후 setOutstream으로 저장·복원할 수 있어요.
setOutstream (strm, strm')
strm 밑에 깔린 스트림을 플러시한 다음 새 저수준 스트림 strm'을 할당해요. strm에서의 향후 출력은 strm'으로 재지정돼요.
getPosOut strm
스트림 strm의 현재 위치를 돌려줘요. 다른 이유 외에도 스트림이 이 연산을 지원하지 않으면 Io 예외를 발생시켜요. StreamIO.getPosOut을 보세요.
setPosOut (strm, pos)
스트림 strm의 현재 위치를 pos로 설정해요. 다른 이유 외에도 스트림이 이 연산을 지원하지 않으면 Io 예외를 발생시켜요. StreamIO.setPosOut을 보세요.