mirror of
https://github.com/ashinn/chibi-scheme.git
synced 2025-07-08 05:27:35 +02:00
Adding binary custom ports.
This commit is contained in:
parent
f85c7ffa6f
commit
d945e744e1
6 changed files with 106 additions and 3 deletions
|
@ -5,6 +5,7 @@
|
||||||
port->list port->string-list port->sexp-list port->string
|
port->list port->string-list port->sexp-list port->string
|
||||||
file-position set-file-position! seek/set seek/cur seek/end
|
file-position set-file-position! seek/set seek/cur seek/end
|
||||||
make-custom-input-port make-custom-output-port
|
make-custom-input-port make-custom-output-port
|
||||||
|
make-custom-binary-input-port make-custom-binary-output-port
|
||||||
make-null-output-port make-null-input-port
|
make-null-output-port make-null-input-port
|
||||||
make-broadcast-port make-concatenated-port
|
make-broadcast-port make-concatenated-port
|
||||||
make-generated-input-port make-filtered-output-port
|
make-generated-input-port make-filtered-output-port
|
||||||
|
|
|
@ -228,19 +228,53 @@
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; custom port utilities
|
;; custom port utilities
|
||||||
|
|
||||||
|
;;> \var{read} is a procedure of three arguments:
|
||||||
|
;;> \scheme{(lambda (str start end) ...)} which should fill \var{str} from
|
||||||
|
;;> \var{start} to \var{end} with bytes, returning the actual number
|
||||||
|
;;> of bytes filled.
|
||||||
|
|
||||||
(define (make-custom-input-port read . o)
|
(define (make-custom-input-port read . o)
|
||||||
(let ((seek (and (pair? o) (car o)))
|
(let ((seek (and (pair? o) (car o)))
|
||||||
(close (and (pair? o) (pair? (cdr o)) (car (cdr o)))))
|
(close (and (pair? o) (pair? (cdr o)) (car (cdr o)))))
|
||||||
(%make-custom-input-port read seek close)))
|
(%make-custom-input-port read seek close)))
|
||||||
|
|
||||||
|
;;> \var{write} is a procedure of three arguments:
|
||||||
|
;;> \scheme{(lambda (str start end) ...)} which should write the bytes of
|
||||||
|
;;> \var{str} from \var{start} to \var{end}, returning the actual
|
||||||
|
;;> number of bytes written.
|
||||||
|
|
||||||
(define (make-custom-output-port write . o)
|
(define (make-custom-output-port write . o)
|
||||||
(let ((seek (and (pair? o) (car o)))
|
(let ((seek (and (pair? o) (car o)))
|
||||||
(close (and (pair? o) (pair? (cdr o)) (car (cdr o)))))
|
(close (and (pair? o) (pair? (cdr o)) (car (cdr o)))))
|
||||||
(%make-custom-output-port write seek close)))
|
(%make-custom-output-port write seek close)))
|
||||||
|
|
||||||
|
;;> Similar to \scheme{make-custom-input-port} but returns a binary
|
||||||
|
;;> port, and \var{read} receives a bytevector to fill instead of a
|
||||||
|
;;> string.
|
||||||
|
|
||||||
|
(define (make-custom-binary-input-port read . o)
|
||||||
|
(let ((seek (and (pair? o) (car o)))
|
||||||
|
(close (and (pair? o) (pair? (cdr o)) (car (cdr o)))))
|
||||||
|
(%make-custom-binary-input-port read seek close)))
|
||||||
|
|
||||||
|
;;> Similar to \scheme{make-custom-output-port} but returns a binary
|
||||||
|
;;> port, and \var{write} receives data from a bytevector instead of a
|
||||||
|
;;> string.
|
||||||
|
|
||||||
|
(define (make-custom-binary-output-port write . o)
|
||||||
|
(let ((seek (and (pair? o) (car o)))
|
||||||
|
(close (and (pair? o) (pair? (cdr o)) (car (cdr o)))))
|
||||||
|
(%make-custom-binary-output-port write seek close)))
|
||||||
|
|
||||||
|
;;> A simple /dev/null port which accepts and does nothing with any
|
||||||
|
;;> data written to it.
|
||||||
|
|
||||||
(define (make-null-output-port)
|
(define (make-null-output-port)
|
||||||
(make-custom-output-port (lambda (str start end) 0)))
|
(make-custom-output-port (lambda (str start end) 0)))
|
||||||
|
|
||||||
|
;;> A port to broadcast everything written to it to multiple output
|
||||||
|
;;> ports.
|
||||||
|
|
||||||
(define (make-broadcast-port . ports)
|
(define (make-broadcast-port . ports)
|
||||||
(make-custom-output-port
|
(make-custom-output-port
|
||||||
(lambda (str start end)
|
(lambda (str start end)
|
||||||
|
@ -249,6 +283,9 @@
|
||||||
(for-each (lambda (p) (%write-string str n p)) ports)
|
(for-each (lambda (p) (%write-string str n p)) ports)
|
||||||
n))))
|
n))))
|
||||||
|
|
||||||
|
;;> An output port which runs all output (in arbitrary string chunks)
|
||||||
|
;;> through the \var{filter} procedure.
|
||||||
|
|
||||||
(define (make-filtered-output-port filter out)
|
(define (make-filtered-output-port filter out)
|
||||||
(make-custom-output-port
|
(make-custom-output-port
|
||||||
(lambda (str start end)
|
(lambda (str start end)
|
||||||
|
@ -258,6 +295,9 @@
|
||||||
(if (string? s2)
|
(if (string? s2)
|
||||||
(%write-string s2 (string-length s2) out))))))
|
(%write-string s2 (string-length s2) out))))))
|
||||||
|
|
||||||
|
;;> An input port which acts as all of the \var{ports} concatenated
|
||||||
|
;;> together in order.
|
||||||
|
|
||||||
(define (make-concatenated-port . ports)
|
(define (make-concatenated-port . ports)
|
||||||
(make-custom-input-port
|
(make-custom-input-port
|
||||||
(lambda (str start end)
|
(lambda (str start end)
|
||||||
|
@ -281,9 +321,16 @@
|
||||||
(string-copy! str i s 0 len))
|
(string-copy! str i s 0 len))
|
||||||
(lp (+ i len)))))))))))))
|
(lp (+ i len)))))))))))))
|
||||||
|
|
||||||
|
;;> A /dev/null input port which always returns \scheme{eof-object}.
|
||||||
|
|
||||||
(define (make-null-input-port)
|
(define (make-null-input-port)
|
||||||
(make-concatenated-port))
|
(make-concatenated-port))
|
||||||
|
|
||||||
|
;;> A utility to represent a port generated in chunks by the thunk
|
||||||
|
;;> \var{generator}, which should return a single string representing
|
||||||
|
;;> the next input to buffer, or \scheme{#f} when there is no more
|
||||||
|
;;> input.
|
||||||
|
|
||||||
(define (make-generated-input-port generator)
|
(define (make-generated-input-port generator)
|
||||||
(let ((buf "")
|
(let ((buf "")
|
||||||
(len 0)
|
(len 0)
|
||||||
|
@ -318,6 +365,9 @@
|
||||||
(string-copy! str i buf offset len)
|
(string-copy! str i buf offset len)
|
||||||
(lp (+ i (- len offset)))))))))))))))
|
(lp (+ i (- len offset)))))))))))))))
|
||||||
|
|
||||||
|
;;> An input port which runs all input (in arbitrary string chunks)
|
||||||
|
;;> through the \var{filter} procedure.
|
||||||
|
|
||||||
(define (make-filtered-input-port filter in)
|
(define (make-filtered-input-port filter in)
|
||||||
(make-generated-input-port
|
(make-generated-input-port
|
||||||
(lambda ()
|
(lambda ()
|
||||||
|
|
|
@ -31,6 +31,12 @@
|
||||||
(define-c sexp (%make-custom-output-port "sexp_make_custom_output_port")
|
(define-c sexp (%make-custom-output-port "sexp_make_custom_output_port")
|
||||||
((value ctx sexp) (value self sexp) sexp sexp sexp))
|
((value ctx sexp) (value self sexp) sexp sexp sexp))
|
||||||
|
|
||||||
|
(define-c sexp (%make-custom-binary-input-port "sexp_make_custom_binary_input_port")
|
||||||
|
((value ctx sexp) (value self sexp) sexp sexp sexp))
|
||||||
|
|
||||||
|
(define-c sexp (%make-custom-binary-output-port "sexp_make_custom_binary_output_port")
|
||||||
|
((value ctx sexp) (value self sexp) sexp sexp sexp))
|
||||||
|
|
||||||
(define-c sexp (open-input-bytevector "sexp_open_input_bytevector")
|
(define-c sexp (open-input-bytevector "sexp_open_input_bytevector")
|
||||||
((value ctx sexp) (value self sexp) sexp))
|
((value ctx sexp) (value self sexp) sexp))
|
||||||
(define-c sexp (open-output-bytevector "sexp_open_output_bytevector")
|
(define-c sexp (open-output-bytevector "sexp_open_output_bytevector")
|
||||||
|
|
|
@ -181,6 +181,8 @@ static sexp sexp_make_custom_port (sexp ctx, sexp self, char *mode,
|
||||||
res = sexp_make_input_port(ctx, in, SEXP_FALSE);
|
res = sexp_make_input_port(ctx, in, SEXP_FALSE);
|
||||||
sexp_port_cookie(res) = vec; /* for gc preserving */
|
sexp_port_cookie(res) = vec; /* for gc preserving */
|
||||||
}
|
}
|
||||||
|
if (mode && mode[0] == 'w')
|
||||||
|
sexp_pointer_tag(res) = SEXP_OPORT;
|
||||||
sexp_gc_release1(ctx);
|
sexp_gc_release1(ctx);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -234,6 +236,20 @@ sexp sexp_make_custom_output_port (sexp ctx, sexp self,
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sexp sexp_make_custom_binary_input_port (sexp ctx, sexp self,
|
||||||
|
sexp read, sexp seek, sexp close) {
|
||||||
|
sexp res = sexp_make_custom_input_port(ctx, self, read, seek, close);
|
||||||
|
sexp_port_binaryp(res) = 1;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
sexp sexp_make_custom_binary_output_port (sexp ctx, sexp self,
|
||||||
|
sexp write, sexp seek, sexp close) {
|
||||||
|
sexp res = sexp_make_custom_output_port(ctx, self, write, seek, close);
|
||||||
|
sexp_port_binaryp(res) = 1;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
sexp sexp_bytes_to_string (sexp ctx, sexp vec) {
|
sexp sexp_bytes_to_string (sexp ctx, sexp vec) {
|
||||||
sexp res;
|
sexp res;
|
||||||
#if SEXP_USE_PACKED_STRINGS
|
#if SEXP_USE_PACKED_STRINGS
|
||||||
|
|
4
sexp.c
4
sexp.c
|
@ -1441,7 +1441,7 @@ int sexp_buffered_read_char (sexp ctx, sexp p) {
|
||||||
} else if (sexp_port_customp(p)) {
|
} else if (sexp_port_customp(p)) {
|
||||||
sexp_gc_preserve1(ctx, tmp);
|
sexp_gc_preserve1(ctx, tmp);
|
||||||
tmp = sexp_list2(ctx, SEXP_ZERO, sexp_make_fixnum(SEXP_PORT_BUFFER_SIZE));
|
tmp = sexp_list2(ctx, SEXP_ZERO, sexp_make_fixnum(SEXP_PORT_BUFFER_SIZE));
|
||||||
tmp = sexp_cons(ctx, sexp_port_buffer(p), tmp);
|
tmp = sexp_cons(ctx, sexp_port_binaryp(p) ? sexp_string_bytes(sexp_port_buffer(p)) : sexp_port_buffer(p), tmp);
|
||||||
tmp = sexp_apply(ctx, sexp_port_reader(p), tmp);
|
tmp = sexp_apply(ctx, sexp_port_reader(p), tmp);
|
||||||
if (sexp_fixnump(tmp) && sexp_unbox_fixnum(tmp) > 0) {
|
if (sexp_fixnump(tmp) && sexp_unbox_fixnum(tmp) > 0) {
|
||||||
sexp_port_offset(p) = 0;
|
sexp_port_offset(p) = 0;
|
||||||
|
@ -1518,7 +1518,7 @@ int sexp_buffered_flush (sexp ctx, sexp p, int forcep) {
|
||||||
sexp_gc_preserve1(ctx, tmp);
|
sexp_gc_preserve1(ctx, tmp);
|
||||||
if (sexp_port_customp(p)) { /* custom port */
|
if (sexp_port_customp(p)) { /* custom port */
|
||||||
tmp = sexp_list2(ctx, SEXP_ZERO, sexp_make_fixnum(sexp_port_offset(p)));
|
tmp = sexp_list2(ctx, SEXP_ZERO, sexp_make_fixnum(sexp_port_offset(p)));
|
||||||
tmp = sexp_cons(ctx, sexp_port_buffer(p), tmp);
|
tmp = sexp_cons(ctx, sexp_port_binaryp(p) ? sexp_string_bytes(sexp_port_buffer(p)) : sexp_port_buffer(p), tmp);
|
||||||
tmp = sexp_apply(ctx, sexp_port_writer(p), tmp);
|
tmp = sexp_apply(ctx, sexp_port_writer(p), tmp);
|
||||||
res = (sexp_fixnump(tmp) && sexp_unbox_fixnum(tmp) > 0) ? 0 : -1;
|
res = (sexp_fixnump(tmp) && sexp_unbox_fixnum(tmp) > 0) ? 0 : -1;
|
||||||
} else { /* string port */
|
} else { /* string port */
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
|
|
||||||
(cond-expand
|
(cond-expand
|
||||||
(modules (import (chibi io) (only (chibi test) test-begin test test-end)))
|
(modules
|
||||||
|
(import (chibi io)
|
||||||
|
(only (scheme base) read-bytevector write-bytevector)
|
||||||
|
(only (chibi test) test-begin test test-end)))
|
||||||
(else #f))
|
(else #f))
|
||||||
|
|
||||||
(test-begin "io")
|
(test-begin "io")
|
||||||
|
@ -86,4 +89,31 @@
|
||||||
(display "abc" out)
|
(display "abc" out)
|
||||||
(close-output-port out)))))
|
(close-output-port out)))))
|
||||||
|
|
||||||
|
(let ((in (make-custom-binary-input-port
|
||||||
|
(let ((i 0))
|
||||||
|
(lambda (bv start end)
|
||||||
|
(do ((j start (+ j 1)))
|
||||||
|
((= j end))
|
||||||
|
(bytevector-u8-set! bv j (modulo (+ j i) 256)))
|
||||||
|
(if (> end 0)
|
||||||
|
(set! i (bytevector-u8-ref bv (- end 1))))
|
||||||
|
(- end start))))))
|
||||||
|
(test #u8(0 1 2 3) (read-bytevector 4 in))
|
||||||
|
(test #u8(4 5 6 7) (read-bytevector 4 in))
|
||||||
|
(test 7 (bytevector-u8-ref (read-bytevector 256 in) 255))
|
||||||
|
(test 6 (bytevector-u8-ref (read-bytevector 1024 in) 1022)))
|
||||||
|
|
||||||
|
(let* ((sum 0)
|
||||||
|
(out (make-custom-binary-output-port
|
||||||
|
(lambda (bv start end)
|
||||||
|
(do ((i start (+ i 1))
|
||||||
|
(x 0 (+ x (bytevector-u8-ref bv i))))
|
||||||
|
((= i end) (set! sum x)))))))
|
||||||
|
(write-bytevector #u8(0 1 2 3) out)
|
||||||
|
(flush-output out)
|
||||||
|
(test 6 sum)
|
||||||
|
(write-bytevector #u8(100) out)
|
||||||
|
(flush-output out)
|
||||||
|
(test 106 sum))
|
||||||
|
|
||||||
(test-end)
|
(test-end)
|
||||||
|
|
Loading…
Add table
Reference in a new issue