* lineio.scm (make-line-buffering-input-port): Properly test for
[bpt/guile.git] / ice-9 / lineio.scm
1 ;;; installed-scm-file
2
3 ;;;; Copyright (C) 1996 Free Software Foundation, Inc.
4 ;;;;
5 ;;;; This program is free software; you can redistribute it and/or modify
6 ;;;; it under the terms of the GNU General Public License as published by
7 ;;;; the Free Software Foundation; either version 2, or (at your option)
8 ;;;; any later version.
9 ;;;;
10 ;;;; This program is distributed in the hope that it will be useful,
11 ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ;;;; GNU General Public License for more details.
14 ;;;;
15 ;;;; You should have received a copy of the GNU General Public License
16 ;;;; along with this software; see the file COPYING. If not, write to
17 ;;;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
18 ;;;;
19
20 \f
21
22 (define-module #/ice-9/lineio)
23
24 \f
25 ;;; {Line Buffering Input Ports}
26 ;;;
27 ;;; [This is a work-around to get past certain deficiencies in the capabilities
28 ;;; of ports. Eventually, ports should be fixed and this module nuked.]
29 ;;;
30 ;;; A line buffering input port supports:
31 ;;;
32 ;;; read-string which returns the next line of input
33 ;;; unread-string which pushes a line back onto the stream
34 ;;;
35 ;;; Normally a "line" is all characters up to and including a newline.
36 ;;; If lines are put back using unread-string, they can be broken arbitrarily
37 ;;; -- that is, read-string returns strings passed to unread-string (or
38 ;;; shared substrings of them).
39 ;;;
40
41 ;; read-string port
42 ;; unread-string port str
43 ;; Read (or buffer) a line from PORT.
44 ;;
45 ;; Not all ports support these functions -- only those with
46 ;; 'unread-string and 'read-string properties, bound to hooks
47 ;; implementing these functions.
48 ;;
49 (define-public (unread-string str line-buffering-input-port)
50 ((object-property line-buffering-input-port 'unread-string) str))
51
52 ;;
53 (define-public (read-string line-buffering-input-port)
54 ((object-property line-buffering-input-port 'read-string)))
55
56
57 (define-public (lineio-port? port)
58 (not (not (object-property port 'read-string))))
59
60 ;; make-line-buffering-input-port port
61 ;; Return a wrapper for PORT. The wrapper handles read-string/unread-string.
62 ;;
63 ;; The port returned by this function reads newline terminated lines from PORT.
64 ;; It buffers these characters internally, and parsels them out via calls
65 ;; to read-char, read-string, and unread-string.
66 ;;
67
68 (define-public (make-line-buffering-input-port underlying-port)
69 (let* (;; buffers - a list of strings put back by unread-string or cached
70 ;; using read-line.
71 ;;
72 (buffers '())
73
74 ;; getc - return the next character from a buffer or from the underlying
75 ;; port.
76 ;;
77 (getc (lambda ()
78 (if (not buffers)
79 (read-char underlying-port)
80 (let ((c (string-ref (car buffers))))
81 (if (= 1 (string-length (car buffers)))
82 (set! buffers (cdr buffers))
83 (set-car! buffers (make-shared-substring (car buffers) 1)))
84 c))))
85
86 (propogate-close (lambda () (close-port underlying-port)))
87
88 (self (make-soft-port (vector #f #f #f getc propogate-close) "r"))
89
90 (unread-string (lambda (str)
91 (and (< 0 (string-length str))
92 (if (ungetc-char-ready? self)
93 (set! buffers (append! (list str (string (read-char self))) buffers))
94 (set! buffers (cons str buffers))))))
95
96 (read-string (lambda ()
97 (cond
98 ((not (null? buffers))
99 (let ((answer (car buffers)))
100 (set! buffers (cdr buffers))
101 answer))
102 ((ungetc-char-ready? self)
103 (read-line self 'include-newline))
104 (else
105 (read-line underlying-port 'include-newline))))))
106
107 (set-object-property! self 'unread-string unread-string)
108 (set-object-property! self 'read-string read-string)
109 self))
110
111