練習問題 exercise 4 の解答

書き込む文字列をバッファにコピーするのが基本的なアイデアです。バッファに十分な空きが無く途中でバッファを空にする必要がある場合とそうでなく文字列全てをバッファに直接書き込める場合とを考える必要があります。解答例を以下に示します。

open Unix;;
let output_string chan s = let avail = Bytes.length chan.out_buffer - chan.out_pos in if Bytes.length s <= avail then begin Bytes.blit s 0 chan.out_buffer chan.out_pos (Bytes.length s); chan.out_pos <- chan.out_pos + Bytes.length s end else if chan.out_pos = 0 then begin ignore (write chan.out_fd s 0 (Bytes.length s)) end else begin Bytes.blit s 0 chan.out_buffer chan.out_pos avail; let out_buffer_size = Bytes.length chan.out_buffer in ignore (write chan.out_fd chan.out_buffer 0 out_buffer_size); let remaining = Bytes.length s - avail in if remaining < out_buffer_size then begin Bytes.blit s avail chan.out_buffer 0 remaining; chan.out_pos <- remaining end else begin ignore (write chan.out_fd s avail remaining); chan.out_pos <- 0 end end;;
let ex2 () = if Array.length Sys.argv < 3 then begin prerr_string "Usage: test <sources> <dest>"; exit 2; end; let fdin = open_in Sys.argv.(1) in let fdout = open_out Sys.argv.(2) in prerr_endline "copying"; try while true do output_char fdout (input_char fdin) done with End_of_file -> prerr_endline "Done"; output_string fdout "The end.\n"; prerr_endline "Closing"; close_out fdout;; handle_unix_error ex2 ();;
./ex2.byte ex2.ml ex2.out (cat ex2.ml; echo "C'est la fin.") | diff --brief - ex2.out rm ex2.out
* * *