1 /* Guile-R6RS-Libs --- Implementation of R6RS standard libraries.
2 Copyright (C) 2007 Ludovic Courtès <ludovic.courtes@laas.fr>
4 Guile-R6RS-Libs is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
9 Guile-R6RS-Libs is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public
15 License along with Guile-R6RS-Libs; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
23 #include "bytevector.h"
28 /* End-of-file object. */
30 SCM_DEFINE (scm_r6rs_eof_object
, "eof-object", 0, 0, 0,
32 "Return the end-of-file object.")
33 #define FUNC_NAME s_scm_r6rs_eof_object
42 /* We currently don't support specific binary input ports. */
43 #define SCM_VALIDATE_R6RS_BINARY_INPUT_PORT SCM_VALIDATE_INPUT_PORT
45 SCM_DEFINE (scm_r6rs_get_u8
, "get-u8", 1, 0, 0,
47 "Read an octet from @var{port}, a binary input port, "
48 "blocking as necessary.")
49 #define FUNC_NAME s_scm_r6rs_get_u8
54 SCM_VALIDATE_R6RS_BINARY_INPUT_PORT (1, port
);
56 c_result
= scm_getc (port
);
60 result
= SCM_I_MAKINUM ((unsigned char) c_result
);
66 SCM_DEFINE (scm_r6rs_lookahead_u8
, "lookahead-u8", 1, 0, 0,
68 "Like @code{get-u8} but does not update @var{port} to "
69 "point past the octet.")
70 #define FUNC_NAME s_scm_r6rs_lookahead_u8
74 SCM_VALIDATE_R6RS_BINARY_INPUT_PORT (1, port
);
76 result
= scm_peek_char (port
);
77 if (SCM_CHARP (result
))
78 result
= SCM_I_MAKINUM ((signed char) SCM_CHAR (result
));
86 SCM_DEFINE (scm_r6rs_get_bytevector_n
, "get-bytevector-n", 2, 0, 0,
87 (SCM port
, SCM count
),
88 "Read @var{count} octets from @var{port}, blocking as "
89 "necessary and return a bytevector containing the octets "
90 "read. If fewer bytes are available, a bytevector smaller "
91 "than @var{count} is returned.")
92 #define FUNC_NAME s_scm_r6rs_get_bytevector_n
99 SCM_VALIDATE_R6RS_BINARY_INPUT_PORT (1, port
);
100 c_count
= scm_to_uint (count
);
102 c_bv
= (char *) scm_gc_malloc (c_count
, SCM_GC_BYTEVECTOR
);
104 /* XXX: `scm_c_read ()' does not update the port position. */
105 read
= scm_c_read (port
, c_bv
, c_count
);
109 if (SCM_EOF_OBJECT_P (scm_peek_char (port
)))
110 result
= SCM_EOF_VAL
;
112 result
= scm_r6rs_c_take_bytevector (NULL
, 0);
117 c_bv
= (char *) scm_gc_realloc (c_bv
, c_count
, read
,
120 result
= scm_r6rs_c_take_bytevector ((signed char *) c_bv
, read
);
127 SCM_DEFINE (scm_r6rs_get_bytevector_n_x
, "get-bytevector-n!", 4, 0, 0,
128 (SCM port
, SCM bv
, SCM start
, SCM count
),
129 "Read @var{count} bytes from @var{port} and store them "
130 "in @var{bv} starting at index @var{start}. Return either "
131 "the number of bytes actually read or the end-of-file "
133 #define FUNC_NAME s_scm_r6rs_get_bytevector_n_x
137 unsigned c_start
, c_count
, c_len
;
140 SCM_VALIDATE_R6RS_BINARY_INPUT_PORT (1, port
);
141 SCM_VALIDATE_R6RS_BYTEVECTOR (2, bv
);
142 c_start
= scm_to_uint (start
);
143 c_count
= scm_to_uint (count
);
145 c_bv
= (char *) SCM_R6RS_BYTEVECTOR_CONTENTS (bv
);
146 c_len
= SCM_R6RS_BYTEVECTOR_LENGTH (bv
);
148 if (EXPECT_FALSE (c_start
+ c_count
> c_len
))
149 scm_out_of_range (FUNC_NAME
, count
);
151 c_read
= scm_c_read (port
, c_bv
+ c_start
, c_count
);
154 if (SCM_EOF_OBJECT_P (scm_peek_char (port
)))
155 result
= SCM_EOF_VAL
;
157 result
= SCM_I_MAKINUM (0);
160 result
= scm_from_size_t (c_read
);
167 SCM_DEFINE (scm_r6rs_get_bytevector_some
, "get-bytevector-some", 1, 0, 0,
169 "Read from @var{port}, blocking as necessary, until data "
170 "are available or and end-of-file is reached. Return either "
171 "a new bytevector containing the data read or the "
172 "end-of-file object.")
173 #define FUNC_NAME s_scm_r6rs_get_bytevector_some
175 /* Read at least one byte, unless the end-of-file is already reached, and
176 read while characters are available (buffered). */
183 SCM_VALIDATE_R6RS_BINARY_INPUT_PORT (1, port
);
186 c_bv
= (char *) scm_gc_malloc (c_len
, SCM_GC_BYTEVECTOR
);
193 if (c_total
+ 1 > c_len
)
195 /* Grow the bytevector. */
196 c_bv
= (char *) scm_gc_realloc (c_bv
, c_len
, c_len
* 2,
201 /* We can't use `scm_c_read ()' since it blocks. */
202 c_chr
= scm_getc (port
);
205 c_bv
[c_total
] = (char) c_chr
;
209 while ((scm_is_true (scm_char_ready_p (port
)))
210 && (!SCM_EOF_OBJECT_P (scm_peek_char (port
))));
214 result
= SCM_EOF_VAL
;
215 scm_gc_free (c_bv
, c_len
, SCM_GC_BYTEVECTOR
);
221 /* Shrink the bytevector. */
222 c_bv
= (char *) scm_gc_realloc (c_bv
, c_len
, c_total
,
224 c_len
= (unsigned) c_total
;
227 result
= scm_r6rs_c_take_bytevector ((signed char *) c_bv
, c_len
);
234 SCM_DEFINE (scm_r6rs_get_bytevector_all
, "get-bytevector-all", 1, 0, 0,
236 "Read from @var{port}, blocking as necessary, until "
237 "the end-of-file is reached. Return either "
238 "a new bytevector containing the data read or the "
239 "end-of-file object (if no data were available).")
240 #define FUNC_NAME s_scm_r6rs_get_bytevector_all
244 unsigned c_len
, c_count
;
245 size_t c_read
, c_total
;
247 SCM_VALIDATE_R6RS_BINARY_INPUT_PORT (1, port
);
249 c_len
= c_count
= 4096;
250 c_bv
= (char *) scm_gc_malloc (c_len
, SCM_GC_BYTEVECTOR
);
251 c_total
= c_read
= 0;
255 if (c_total
+ c_read
> c_len
)
257 /* Grow the bytevector. */
258 c_bv
= (char *) scm_gc_realloc (c_bv
, c_len
, c_len
* 2,
264 /* `scm_c_read ()' blocks until C_COUNT bytes are available or EOF is
266 c_read
= scm_c_read (port
, c_bv
+ c_total
, c_count
);
267 c_total
+= c_read
, c_count
-= c_read
;
269 while (!SCM_EOF_OBJECT_P (scm_peek_char (port
)));
273 result
= SCM_EOF_VAL
;
274 scm_gc_free (c_bv
, c_len
, SCM_GC_BYTEVECTOR
);
280 /* Shrink the bytevector. */
281 c_bv
= (char *) scm_gc_realloc (c_bv
, c_len
, c_total
,
283 c_len
= (unsigned) c_total
;
286 result
= scm_r6rs_c_take_bytevector ((signed char *) c_bv
, c_len
);
297 /* We currently don't support specific binary input ports. */
298 #define SCM_VALIDATE_R6RS_BINARY_OUTPUT_PORT SCM_VALIDATE_OUTPUT_PORT
301 SCM_DEFINE (scm_r6rs_put_u8
, "put-u8", 2, 0, 0,
302 (SCM port
, SCM octet
),
303 "Write @var{octet} to binary port @var{port}.")
304 #define FUNC_NAME s_scm_r6rs_put_u8
308 SCM_VALIDATE_R6RS_BINARY_OUTPUT_PORT (1, port
);
309 c_octet
= scm_to_uint8 (octet
);
311 scm_putc ((char) c_octet
, port
);
313 return SCM_UNSPECIFIED
;
317 SCM_DEFINE (scm_r6rs_put_bytevector
, "put-bytevector", 2, 2, 0,
318 (SCM port
, SCM bv
, SCM start
, SCM count
),
319 "Write the contents of @var{bv} to @var{port}, optionally "
320 "starting at index @var{start} and limiting to @var{count} "
322 #define FUNC_NAME s_scm_r6rs_put_bytevector
325 unsigned c_start
, c_count
, c_len
;
327 SCM_VALIDATE_R6RS_BINARY_OUTPUT_PORT (1, port
);
328 SCM_VALIDATE_R6RS_BYTEVECTOR (2, bv
);
330 c_len
= SCM_R6RS_BYTEVECTOR_LENGTH (bv
);
331 c_bv
= SCM_R6RS_BYTEVECTOR_CONTENTS (bv
);
333 if (start
!= SCM_UNDEFINED
)
335 c_start
= scm_to_uint (start
);
337 if (count
!= SCM_UNDEFINED
)
339 c_count
= scm_to_uint (count
);
340 if (EXPECT_FALSE (c_start
+ c_count
> c_len
))
341 scm_out_of_range (FUNC_NAME
, count
);
345 if (EXPECT_FALSE (c_start
>= c_len
))
346 scm_out_of_range (FUNC_NAME
, start
);
348 c_count
= c_len
- c_start
;
352 c_start
= 0, c_count
= c_len
;
354 scm_c_write (port
, c_bv
+ c_start
, c_count
);
356 return SCM_UNSPECIFIED
;
361 /* Initialization. */
364 scm_init_r6rs_ports (void)
369 /* arch-tag: c041ffd6-8871-40e8-a25a-d0f8768a71dc