1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-04-30 03:40:34 +02:00

Add get-string-n' and get-string-n!' for R6RS ports

* libguile/r6rs-ports.c (scm_get_string_n_x): Implement `get-string-n!'
  in C for efficiency.
* libguile/r6rs-ports.h: Add prototype for this function.
* module/ice-9/binary-ports.scm: Export `get-string-n!'.

* module/rnrs/io/ports.scm (get-string-n): Implement based on
  `get-string-n!'.
  Export both `get-string-n!' and `get-string-n'.
* module/rnrs.scm: Also export these.

* test-suite/tests/r6rs-ports.test (8.2.9 Textual input): Add a few
  tests for `get-string-n' and `get-string-n!'.

Signed-off-by: Ludovic Courtès <ludo@gnu.org>
This commit is contained in:
Andreas Rottmann 2011-03-13 22:39:14 +01:00 committed by Ludovic Courtès
parent ca33b501a9
commit a6c377f7d8
6 changed files with 78 additions and 5 deletions

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2009, 2010 Free Software Foundation, Inc. /* Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc.
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License * modify it under the terms of the GNU Lesser General Public License
@ -1221,6 +1221,46 @@ SCM_DEFINE (scm_i_make_transcoded_port,
} }
#undef FUNC_NAME #undef FUNC_NAME
/* Textual I/O */
SCM_DEFINE (scm_get_string_n_x,
"get-string-n!", 4, 0, 0,
(SCM port, SCM str, SCM start, SCM count),
"Read up to @var{count} characters from @var{port} into "
"@var{str}, starting at @var{start}. If no characters "
"can be read before the end of file is encountered, the end "
"of file object is returned. Otherwise, the number of "
"characters read is returned.")
#define FUNC_NAME s_scm_get_string_n_x
{
size_t c_start, c_count, c_len, c_end, j;
scm_t_wchar c;
SCM_VALIDATE_OPINPORT (1, port);
SCM_VALIDATE_STRING (2, str);
c_len = scm_c_string_length (str);
c_start = scm_to_size_t (start);
c_count = scm_to_size_t (count);
c_end = c_start + c_count;
if (SCM_UNLIKELY (c_end > c_len))
scm_out_of_range (FUNC_NAME, count);
for (j = c_start; j < c_end; j++)
{
c = scm_getc (port);
if (c == EOF)
{
size_t chars_read = j - c_start;
return chars_read == 0 ? SCM_EOF_VAL : scm_from_size_t (chars_read);
}
scm_c_string_set_x (str, j, SCM_MAKE_CHAR (c));
}
return count;
}
#undef FUNC_NAME
/* Initialization. */ /* Initialization. */

View file

@ -1,7 +1,7 @@
#ifndef SCM_R6RS_PORTS_H #ifndef SCM_R6RS_PORTS_H
#define SCM_R6RS_PORTS_H #define SCM_R6RS_PORTS_H
/* Copyright (C) 2009, 2010 Free Software Foundation, Inc. /* Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc.
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License * modify it under the terms of the GNU Lesser General Public License
@ -38,6 +38,7 @@ SCM_API SCM scm_put_u8 (SCM, SCM);
SCM_API SCM scm_put_bytevector (SCM, SCM, SCM, SCM); SCM_API SCM scm_put_bytevector (SCM, SCM, SCM, SCM);
SCM_API SCM scm_open_bytevector_output_port (SCM); SCM_API SCM scm_open_bytevector_output_port (SCM);
SCM_API SCM scm_make_custom_binary_output_port (SCM, SCM, SCM, SCM, SCM); SCM_API SCM scm_make_custom_binary_output_port (SCM, SCM, SCM, SCM, SCM);
SCM_API SCM scm_get_string_n_x (SCM, SCM, SCM, SCM);
SCM_API void scm_init_r6rs_ports (void); SCM_API void scm_init_r6rs_ports (void);
SCM_INTERNAL void scm_register_r6rs_ports (void); SCM_INTERNAL void scm_register_r6rs_ports (void);

View file

@ -37,6 +37,7 @@
get-bytevector-n! get-bytevector-n!
get-bytevector-some get-bytevector-some
get-bytevector-all get-bytevector-all
get-string-n!
put-u8 put-u8
put-bytevector put-bytevector
open-bytevector-output-port open-bytevector-output-port

View file

@ -182,7 +182,8 @@
make-custom-textual-output-port make-custom-textual-output-port
call-with-string-output-port call-with-string-output-port
flush-output-port put-string flush-output-port put-string
get-char get-datum get-line get-string-all lookahead-char get-char get-datum get-line get-string-all get-string-n get-string-n!
lookahead-char
put-char put-datum put-string put-char put-datum put-string
standard-input-port standard-output-port standard-error-port standard-input-port standard-output-port standard-error-port

View file

@ -68,7 +68,8 @@
put-u8 put-bytevector put-u8 put-bytevector
;; textual input ;; textual input
get-char get-datum get-line get-string-all lookahead-char get-char get-datum get-line get-string-all get-string-n get-string-n!
lookahead-char
;; textual output ;; textual output
put-char put-datum put-string put-char put-datum put-string
@ -386,6 +387,17 @@ return the characters accumulated in that port."
(define (get-string-all port) (define (get-string-all port)
(with-i/o-decoding-error (read-delimited "" port 'concat))) (with-i/o-decoding-error (read-delimited "" port 'concat)))
(define (get-string-n port count)
"Read up to @var{count} characters from @var{port}.
If no characters could be read before encountering the end of file,
return the end-of-file object, otherwise return a string containing
the characters read."
(let* ((s (make-string count))
(rv (get-string-n! port s 0 count)))
(cond ((eof-object? rv) rv)
((= rv count) s)
(else (substring/shared s 0 rv)))))
(define (lookahead-char port) (define (lookahead-char port)
(with-i/o-decoding-error (peek-char port))) (with-i/o-decoding-error (peek-char port)))

View file

@ -567,6 +567,24 @@
(put-string tp "The letter λ cannot be represented in Latin-1.") (put-string tp "The letter λ cannot be represented in Latin-1.")
#f))))) #f)))))
(with-test-prefix "8.2.9 Textual input"
(pass-if "get-string-n [short]"
(let ((port (open-input-string "GNU Guile")))
(string=? "GNU " (get-string-n port 4))))
(pass-if "get-string-n [long]"
(let ((port (open-input-string "GNU Guile")))
(string=? "GNU Guile" (get-string-n port 256))))
(pass-if "get-string-n [eof]"
(let ((port (open-input-string "")))
(eof-object? (get-string-n port 4))))
(pass-if "get-string-n! [short]"
(let ((port (open-input-string "GNU Guile"))
(s (string-copy "Isn't XXX great?")))
(and (= 3 (get-string-n! port s 6 3))
(string=? s "Isn't GNU great?")))))
;;; Local Variables: ;;; Local Variables:
;;; mode: scheme ;;; mode: scheme
;;; eval: (put 'guard 'scheme-indent-function 1) ;;; eval: (put 'guard 'scheme-indent-function 1)