File: pipe-through-eventdriven.ml

package info (click to toggle)
ocamlnet 2.2.9-8
  • links: PTS, VCS
  • area: main
  • in suites: squeeze
  • size: 17,724 kB
  • ctags: 10,053
  • sloc: ml: 63,928; ansic: 1,973; makefile: 800; sh: 651
file content (57 lines) | stat: -rw-r--r-- 2,187 bytes parent folder | download | duplicates (12)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
let buffer_length = 1024 in
let in_buffer = String.create buffer_length in
let out_buffer = String.create buffer_length in
let out_buffer_length = ref 0 in
let end_of_stream = ref false in
let waiting_for_input = ref true in
let waiting_for_output = ref false in

while !waiting_for_input or !waiting_for_output do
  (* If !waiting_for_input, we are interested whether input arrives.
   * If !waiting_for_output, we are interested whether output is 
   * possible.
   *)
  let (in_fd, out_fd, oob_fd) = 
    Unix.select (if !waiting_for_input then [ Unix.stdin] else [])
                (if !waiting_for_output then [ Unix.stdout] else [])
                []
                (-.1.0) in

  (* If in_fd is non-empty, input is immediately possible and will 
   * not block. 
   *)
  if in_fd <> [] then begin
    (* How many bytes we can read in depends on the amount of 
     * free space in the output buffer.
     *)
    let n = buffer_length - !out_buffer_length in
    assert(n > 0);
    let n' = Unix.read Unix.stdin in_buffer 0 n in
    end_of_stream := (n' = 0);
    (* Convert the bytes, and append them to the output buffer. *)
    let converted = String.uppercase (String.sub in_buffer 0 n') in
    String.blit converted 0 out_buffer !out_buffer_length n';
    out_buffer_length := !out_buffer_length + n';
  end;

  (* If out_fd is non-empty, output is immediately possible and 
   * will not block.
   *)
  if out_fd <> [] then begin
    (* Try to write !out_buffer_length bytes. *)
    let n' = Unix.write Unix.stdout out_buffer 0 !out_buffer_length in
    (* Remove the written bytes from the out_buffer: *)
    String.blit out_buffer n' out_buffer 0 (!out_buffer_length - n');
    out_buffer_length := !out_buffer_length - n'
  end;

  (* Now find out which event is interesting next: *)

  waiting_for_input :=                   (* Input is interesting if...*)
    not !end_of_stream &&                (* ...we are before the end *)
    !out_buffer_length < buffer_length;  (* ...there is space in the out buf *)

  waiting_for_output :=                  (* Output is interesting if... *)
    !out_buffer_length > 0;              (* ...there is material to output *)

done