Call `%init-rdelim-builtins'.
[bpt/guile.git] / ice-9 / rdelim.scm
CommitLineData
9d774814
GH
1;;; installed-scm-file
2
6d36532c 3;;;; Copyright (C) 1997, 1999, 2000, 2001 Free Software Foundation, Inc.
9d774814
GH
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, Inc., 59 Temple Place, Suite 330,
18;;;; Boston, MA 02111-1307 USA
19;;;;
20\f
21
6d36532c
GH
22;;; This is the Scheme part of the module for delimited I/O. It's
23;;; similar to (scsh rdelim) but somewhat incompatible.
9d774814
GH
24
25(define-module (ice-9 rdelim))
26
43fd4402
MV
27(%init-rdelim-builtins)
28
9d774814 29(export read-line read-line! read-delimited read-delimited!)
6d36532c 30(export %read-delimited! %read-line write-line) ; C
9d774814
GH
31
32(define (read-line! string . maybe-port)
33 ;; corresponds to SCM_LINE_INCREMENTORS in libguile.
34 (define scm-line-incrementors "\n")
35
36 (let* ((port (if (pair? maybe-port)
37 (car maybe-port)
38 (current-input-port))))
39 (let* ((rv (%read-delimited! scm-line-incrementors
40 string
41 #t
42 port))
43 (terminator (car rv))
44 (nchars (cdr rv)))
45 (cond ((and (= nchars 0)
46 (eof-object? terminator))
47 terminator)
48 ((not terminator) #f)
49 (else nchars)))))
50
51(define (read-delimited! delims buf . args)
52 (let* ((num-args (length args))
53 (port (if (> num-args 0)
54 (car args)
55 (current-input-port)))
56 (handle-delim (if (> num-args 1)
57 (cadr args)
58 'trim))
59 (start (if (> num-args 2)
60 (caddr args)
61 0))
62 (end (if (> num-args 3)
63 (cadddr args)
64 (string-length buf))))
65 (let* ((rv (%read-delimited! delims
66 buf
67 (not (eq? handle-delim 'peek))
68 port
69 start
70 end))
71 (terminator (car rv))
72 (nchars (cdr rv)))
73 (cond ((or (not terminator) ; buffer filled
74 (eof-object? terminator))
75 (if (zero? nchars)
76 (if (eq? handle-delim 'split)
77 (cons terminator terminator)
78 terminator)
79 (if (eq? handle-delim 'split)
80 (cons nchars terminator)
81 nchars)))
82 (else
83 (case handle-delim
84 ((trim peek) nchars)
85 ((concat) (string-set! buf (+ nchars start) terminator)
86 (+ nchars 1))
87 ((split) (cons nchars terminator))
88 (else (error "unexpected handle-delim value: "
89 handle-delim))))))))
90
91(define (read-delimited delims . args)
92 (let* ((port (if (pair? args)
93 (let ((pt (car args)))
94 (set! args (cdr args))
95 pt)
96 (current-input-port)))
97 (handle-delim (if (pair? args)
98 (car args)
99 'trim)))
bf4aaed2 100 (let loop ((substrings '())
9d774814
GH
101 (total-chars 0)
102 (buf-size 100)) ; doubled each time through.
103 (let* ((buf (make-string buf-size))
104 (rv (%read-delimited! delims
105 buf
106 (not (eq? handle-delim 'peek))
107 port))
108 (terminator (car rv))
109 (nchars (cdr rv))
110 (join-substrings
111 (lambda ()
112 (apply string-append
113 (reverse
114 (cons (if (and (eq? handle-delim 'concat)
115 (not (eof-object? terminator)))
116 (string terminator)
117 "")
118 (cons (substring buf 0 nchars)
119 substrings))))))
120 (new-total (+ total-chars nchars)))
121 (cond ((not terminator)
122 ;; buffer filled.
123 (loop (cons (substring buf 0 nchars) substrings)
124 new-total
125 (* buf-size 2)))
126 ((eof-object? terminator)
127 (if (zero? new-total)
128 (if (eq? handle-delim 'split)
129 (cons terminator terminator)
130 terminator)
131 (if (eq? handle-delim 'split)
132 (cons (join-substrings) terminator)
133 (join-substrings))))
134 (else
135 (case handle-delim
136 ((trim peek concat) (join-substrings))
137 ((split) (cons (join-substrings) terminator))
138
139
140 (else (error "unexpected handle-delim value: "
141 handle-delim)))))))))
142
143;;; read-line [PORT [HANDLE-DELIM]] reads a newline-terminated string
144;;; from PORT. The return value depends on the value of HANDLE-DELIM,
145;;; which may be one of the symbols `trim', `concat', `peek' and
146;;; `split'. If it is `trim' (the default), the trailing newline is
147;;; removed and the string is returned. If `concat', the string is
148;;; returned with the trailing newline intact. If `peek', the newline
149;;; is left in the input port buffer and the string is returned. If
150;;; `split', the newline is split from the string and read-line
151;;; returns a pair consisting of the truncated string and the newline.
152
153(define (read-line . args)
154 (let* ((port (if (null? args)
155 (current-input-port)
156 (car args)))
157 (handle-delim (if (> (length args) 1)
158 (cadr args)
159 'trim))
160 (line/delim (%read-line port))
161 (line (car line/delim))
162 (delim (cdr line/delim)))
163 (case handle-delim
164 ((trim) line)
165 ((split) line/delim)
166 ((concat) (if (and (string? line) (char? delim))
167 (string-append line (string delim))
168 line))
169 ((peek) (if (char? delim)
170 (unread-char delim port))
171 line)
172 (else
173 (error "unexpected handle-delim value: " handle-delim)))))