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 #ifdef HAVE_BYTESWAP_H
24 # include <byteswap.h>
29 /* Assuming 32-bit longs. */
30 # define ULONG_MAX 4294967295UL
39 # define EXPECT __builtin_expect
41 # define EXPECT(_expr, _value) (_expr)
44 #define EXPECT_TRUE(_expr) EXPECT ((_expr), 1)
45 #define EXPECT_FALSE(_expr) EXPECT ((_expr), 0)
49 /* Bytevector type. */
51 SCM_SMOB (scm_tc16_r6rs_bytevector
, "r6rs-bytevector", 0);
53 #define SCM_VALIDATE_R6RS_BYTEVECTOR(_pos, _obj) \
54 SCM_VALIDATE_SMOB ((_pos), (_obj), r6rs_bytevector);
58 make_bytevector (unsigned len
, signed char *contents
)
60 SCM_RETURN_NEWSMOB2 (scm_tc16_r6rs_bytevector
, len
, contents
);
63 #define SCM_R6RS_BYTEVECTOR_LENGTH(_bv) \
64 ((unsigned) SCM_SMOB_DATA (_bv))
65 #define SCM_R6RS_BYTEVECTOR_CONTENTS(_bv) \
66 ((signed char *) SCM_SMOB_DATA_2 (_bv))
68 #define SCM_GC_BYTEVECTOR "r6rs-bytevector"
70 SCM_SMOB_FREE (scm_tc16_r6rs_bytevector
, free_bytevector
, bv
)
75 c_len
= SCM_R6RS_BYTEVECTOR_LENGTH (bv
);
76 c_bv
= SCM_R6RS_BYTEVECTOR_CONTENTS (bv
);
78 scm_gc_free (c_bv
, c_len
, SCM_GC_BYTEVECTOR
);
85 /* General operations. */
87 SCM_SYMBOL (scm_sym_big
, "big");
88 SCM_SYMBOL (scm_sym_little
, "little");
90 /* Host endianness (a symbol). */
91 static SCM native_endianness
= SCM_UNSPECIFIED
;
94 #ifdef HAVE_BYTESWAP_H
95 # define non_native_byteswap_16 bswap_16
96 # define non_native_byteswap_32 bswap_32
98 # error "No byteswap function available."
102 SCM_DEFINE (scm_r6rs_native_endianness
, "native-endianness", 0, 0, 0,
104 "Return a symbol denoting the machine's native endianness.")
105 #define FUNC_NAME s_scm_r6rs_native_endianness
107 return native_endianness
;
111 SCM_DEFINE (scm_r6rs_bytevector_p
, "bytevector?", 1, 0, 0,
113 "Return true if @var{obj} is a bytevector.")
114 #define FUNC_NAME s_scm_r6rs_bytevector_p
116 return (scm_from_bool (SCM_SMOB_PREDICATE (scm_tc16_r6rs_bytevector
,
121 SCM_DEFINE (scm_r6rs_make_bytevector
, "make-bytevector", 1, 1, 0,
123 "Return a newly allocated bytevector of @var{len} bytes, "
124 "optionally filled with @var{fill}.")
125 #define FUNC_NAME s_scm_r6rs_make_bytevector
129 signed char *contents
;
131 SCM_VALIDATE_UINT_COPY (1, len
, c_len
);
132 if (fill
!= SCM_UNDEFINED
)
136 value
= scm_to_int (fill
);
137 if (EXPECT_FALSE ((value
< -128) || (value
> 255)))
138 scm_out_of_range (FUNC_NAME
, fill
);
139 c_fill
= (signed char) value
;
142 contents
= (signed char *) scm_gc_malloc (c_len
, SCM_GC_BYTEVECTOR
);
143 if (fill
!= SCM_UNDEFINED
)
147 for (i
= 0; i
< c_len
; i
++)
148 contents
[i
] = c_fill
;
151 return (make_bytevector (c_len
, contents
));
155 SCM_DEFINE (scm_r6rs_bytevector_length
, "bytevector-length", 1, 0, 0,
157 "Return the length (in bytes) of @var{bv}.")
158 #define FUNC_NAME s_scm_r6rs_bytevector_length
160 SCM_VALIDATE_R6RS_BYTEVECTOR (1, bv
);
162 return (scm_from_uint (SCM_R6RS_BYTEVECTOR_LENGTH (bv
)));
166 SCM_DEFINE (scm_r6rs_bytevector_eq_p
, "bytevector=?", 2, 0, 0,
168 "Return is @var{bv1} equals to @var{bv2}---i.e., if they "
169 "have the same length and contents.")
170 #define FUNC_NAME s_scm_r6rs_bytevector_eq_p
172 SCM result
= SCM_BOOL_F
;
173 unsigned c_len1
, c_len2
;
175 SCM_VALIDATE_R6RS_BYTEVECTOR (1, bv1
);
176 SCM_VALIDATE_R6RS_BYTEVECTOR (2, bv2
);
178 c_len1
= SCM_R6RS_BYTEVECTOR_LENGTH (bv1
);
179 c_len2
= SCM_R6RS_BYTEVECTOR_LENGTH (bv2
);
181 if (c_len1
== c_len2
)
183 signed char *c_bv1
, *c_bv2
;
185 c_bv1
= SCM_R6RS_BYTEVECTOR_CONTENTS (bv1
);
186 c_bv2
= SCM_R6RS_BYTEVECTOR_CONTENTS (bv2
);
188 result
= scm_from_bool (!memcmp (c_bv1
, c_bv2
, c_len1
));
195 SCM_DEFINE (scm_r6rs_bytevector_fill_x
, "bytevector-fill!", 2, 0, 0,
197 "Fill bytevector @var{bv} with @var{fill}, a byte.")
198 #define FUNC_NAME s_scm_r6rs_bytevector_fill_x
201 signed char *c_bv
, c_fill
;
203 SCM_VALIDATE_R6RS_BYTEVECTOR (1, bv
);
204 c_fill
= scm_to_int8 (fill
);
206 c_len
= SCM_R6RS_BYTEVECTOR_LENGTH (bv
);
207 c_bv
= SCM_R6RS_BYTEVECTOR_CONTENTS (bv
);
209 for (i
= 0; i
< c_len
; i
++)
212 return SCM_UNSPECIFIED
;
216 SCM_DEFINE (scm_r6rs_bytevector_copy_x
, "bytevector-copy!", 5, 0, 0,
217 (SCM source
, SCM source_start
, SCM target
, SCM target_start
,
219 "Copy @var{len} bytes from @var{source} into @var{target}, "
220 "starting reading from @var{source_start} (a positive index "
221 "within @var{source}) and start writing at "
222 "@var{target_start}.")
223 #define FUNC_NAME s_scm_r6rs_bytevector_copy_x
225 unsigned c_len
, c_source_len
, c_target_len
;
226 unsigned c_source_start
, c_target_start
;
227 signed char *c_source
, *c_target
;
229 SCM_VALIDATE_R6RS_BYTEVECTOR (1, source
);
230 SCM_VALIDATE_R6RS_BYTEVECTOR (3, target
);
232 c_len
= scm_to_uint (len
);
233 c_source_start
= scm_to_uint (source_start
);
234 c_target_start
= scm_to_uint (target_start
);
236 c_source
= SCM_R6RS_BYTEVECTOR_CONTENTS (source
);
237 c_target
= SCM_R6RS_BYTEVECTOR_CONTENTS (target
);
238 c_source_len
= SCM_R6RS_BYTEVECTOR_LENGTH (source
);
239 c_target_len
= SCM_R6RS_BYTEVECTOR_LENGTH (target
);
241 if (EXPECT_FALSE (c_source_start
+ c_len
> c_source_len
))
242 scm_out_of_range (FUNC_NAME
, source_start
);
243 if (EXPECT_FALSE (c_target_start
+ c_len
> c_target_len
))
244 scm_out_of_range (FUNC_NAME
, target_start
);
246 memcpy (c_target
+ c_target_start
,
247 c_source
+ c_source_start
,
250 return SCM_UNSPECIFIED
;
254 SCM_DEFINE (scm_r6rs_bytevector_copy
, "bytevector-copy", 1, 0, 0,
256 "Return a newly allocated copy of @var{bv}.")
257 #define FUNC_NAME s_scm_r6rs_bytevector_copy
260 signed char *c_bv
, *c_copy
;
262 SCM_VALIDATE_R6RS_BYTEVECTOR (1, bv
);
264 c_len
= SCM_R6RS_BYTEVECTOR_LENGTH (bv
);
265 c_bv
= SCM_R6RS_BYTEVECTOR_CONTENTS (bv
);
267 c_copy
= scm_gc_malloc (c_len
, SCM_GC_BYTEVECTOR
);
268 memcpy (c_copy
, c_bv
, c_len
);
270 return (make_bytevector (c_len
, c_copy
));
275 /* Operations on bytes and octets. */
277 #define OCTET_ACCESSOR_PROLOGUE(_sign) \
278 unsigned c_len, c_index; \
281 SCM_VALIDATE_R6RS_BYTEVECTOR (1, bv); \
282 c_index = scm_to_uint (index); \
284 c_len = SCM_R6RS_BYTEVECTOR_LENGTH (bv); \
285 c_bv = (_sign char *) SCM_R6RS_BYTEVECTOR_CONTENTS (bv); \
287 if (EXPECT_FALSE (c_index >= c_len)) \
288 scm_out_of_range (FUNC_NAME, index);
291 SCM_DEFINE (scm_r6rs_bytevector_u8_ref
, "bytevector-u8-ref", 2, 0, 0,
293 "Return the octet located at @var{index} in @var{bv}.")
294 #define FUNC_NAME s_scm_r6rs_bytevector_u8_ref
296 OCTET_ACCESSOR_PROLOGUE (unsigned);
298 return (SCM_I_MAKINUM (c_bv
[c_index
]));
302 SCM_DEFINE (scm_r6rs_bytevector_s8_ref
, "bytevector-s8-ref", 2, 0, 0,
304 "Return the byte located at @var{index} in @var{bv}.")
305 #define FUNC_NAME s_scm_r6rs_bytevector_u8_ref
307 OCTET_ACCESSOR_PROLOGUE (signed);
309 return (SCM_I_MAKINUM (c_bv
[c_index
]));
313 SCM_DEFINE (scm_r6rs_bytevector_u8_set_x
, "bytevector-u8-set!", 3, 0, 0,
314 (SCM bv
, SCM index
, SCM value
),
315 "Return the octet located at @var{index} in @var{bv}.")
316 #define FUNC_NAME s_scm_r6rs_bytevector_u8_set_x
318 unsigned char c_value
;
320 OCTET_ACCESSOR_PROLOGUE (unsigned);
321 c_value
= scm_to_uint8 (value
);
323 c_bv
[c_index
] = c_value
;
325 return SCM_UNSPECIFIED
;
329 SCM_DEFINE (scm_r6rs_bytevector_s8_set_x
, "bytevector-s8-set!", 3, 0, 0,
330 (SCM bv
, SCM index
, SCM value
),
331 "Return the octet located at @var{index} in @var{bv}.")
332 #define FUNC_NAME s_scm_r6rs_bytevector_u8_set_x
334 unsigned char c_value
;
336 OCTET_ACCESSOR_PROLOGUE (signed);
337 c_value
= scm_to_int8 (value
);
339 c_bv
[c_index
] = c_value
;
341 return SCM_UNSPECIFIED
;
345 #undef OCTET_ACCESSOR_PROLOGUE
348 SCM_DEFINE (scm_r6rs_bytevector_to_u8_list
, "bytevector->u8-list", 1, 0, 0,
350 "Return a newly allocated list of octets containing the "
351 "contents of @var{bv}.")
352 #define FUNC_NAME s_scm_r6rs_bytevector_to_u8_list
358 SCM_VALIDATE_R6RS_BYTEVECTOR (1, bv
);
360 c_len
= SCM_R6RS_BYTEVECTOR_LENGTH (bv
);
361 c_bv
= (unsigned char *) SCM_R6RS_BYTEVECTOR_CONTENTS (bv
);
363 lst
= scm_make_list (scm_from_uint (c_len
), SCM_UNSPECIFIED
);
364 for (i
= 0, pair
= lst
;
366 i
++, pair
= SCM_CDR (pair
))
368 SCM_SETCAR (pair
, SCM_I_MAKINUM (c_bv
[i
]));
375 SCM_DEFINE (scm_r6rs_u8_list_to_bytevector
, "u8-list->bytevector", 1, 0, 0,
377 "Turn @var{lst}, a list of octets, into a bytevector.")
378 #define FUNC_NAME s_scm_r6rs_u8_list_to_bytevector
384 SCM_VALIDATE_LIST_COPYLEN (1, lst
, c_len
);
386 c_bv
= scm_gc_malloc (c_len
, SCM_GC_BYTEVECTOR
);
387 for (i
= 0; i
< c_len
; lst
= SCM_CDR (lst
), i
++)
389 item
= SCM_CAR (lst
);
391 if (EXPECT_TRUE (SCM_I_INUMP (item
)))
395 c_item
= SCM_I_INUM (item
);
396 if (EXPECT_TRUE ((c_item
>= 0) && (c_item
< 256)))
397 c_bv
[i
] = (unsigned char) c_item
;
405 return (make_bytevector (c_len
, (signed char *) c_bv
));
408 scm_gc_free (c_bv
, c_len
, SCM_GC_BYTEVECTOR
);
409 scm_wrong_type_arg (FUNC_NAME
, 1, item
);
415 /* Compute the two's complement of VALUE (a positive integer) on SIZE octets
416 using (2^(SIZE * 8) - VALUE). */
418 twos_complement (mpz_t value
, size_t size
)
420 unsigned long bit_count
;
422 /* We expect BIT_COUNT to fit in a unsigned long thanks to the range
423 checking on SIZE performed earlier. */
424 bit_count
= (unsigned long) size
<< 3UL;
426 if (EXPECT_TRUE (bit_count
< sizeof (unsigned long)))
427 mpz_ui_sub (value
, 1UL << bit_count
, value
);
433 mpz_ui_pow_ui (max
, 2, bit_count
);
434 mpz_sub (value
, max
, value
);
440 bytevector_large_ref (const char *c_bv
, size_t c_size
, int signed_p
,
445 int c_endianness
, negative_p
= 0;
449 if (scm_is_eq (endianness
, scm_sym_big
))
450 negative_p
= c_bv
[0] & 0x80;
452 negative_p
= c_bv
[c_size
- 1] & 0x80;
455 c_endianness
= scm_is_eq (endianness
, scm_sym_big
) ? 1 : -1;
458 mpz_import (c_mpz
, 1 /* 1 word */, 1 /* word order doesn't matter */,
459 c_size
/* word is C_SIZE-byte long */,
461 0 /* nails */, c_bv
);
463 if (signed_p
&& negative_p
)
465 twos_complement (c_mpz
, c_size
);
466 mpz_neg (c_mpz
, c_mpz
);
469 result
= scm_from_mpz (c_mpz
);
470 mpz_clear (c_mpz
); /* FIXME: Needed? */
476 bytevector_large_set (char *c_bv
, size_t c_size
, int signed_p
,
477 SCM value
, SCM endianness
)
479 size_t word_count
, value_size
;
481 int c_endianness
, err
= 0;
483 c_endianness
= scm_is_eq (endianness
, scm_sym_big
) ? 1 : -1;
486 scm_to_mpz (value
, c_mpz
);
487 if (mpz_sgn (c_mpz
) < 0)
489 if (EXPECT_TRUE (signed_p
))
491 mpz_neg (c_mpz
, c_mpz
);
492 twos_complement (c_mpz
, c_size
);
501 value_size
= (mpz_sizeinbase (c_mpz
, 2) + (8 * c_size
)) / (8 * c_size
);
502 if (EXPECT_FALSE (value_size
> c_size
))
508 mpz_export (c_bv
, &word_count
, 1 /* word order doesn't matter */,
509 c_size
, c_endianness
,
510 0 /* nails */, c_mpz
);
511 if (EXPECT_FALSE (word_count
!= 1))
520 #define INTEGER_ACCESSOR_PROLOGUE(_sign) \
521 unsigned c_len, c_index, c_size; \
524 SCM_VALIDATE_R6RS_BYTEVECTOR (1, bv); \
525 c_index = scm_to_uint (index); \
526 c_size = scm_to_uint (size); \
528 c_len = SCM_R6RS_BYTEVECTOR_LENGTH (bv); \
529 c_bv = (_sign char *) SCM_R6RS_BYTEVECTOR_CONTENTS (bv); \
531 /* C_SIZE must have its 3 higher bits set to zero so that \
532 multiplying it by 8 yields a number that fits in an \
534 if (EXPECT_FALSE ((c_size == 0) || (c_size >= (ULONG_MAX >> 3L)))) \
535 scm_out_of_range (FUNC_NAME, size); \
536 if (EXPECT_FALSE (c_index + c_size > c_len)) \
537 scm_out_of_range (FUNC_NAME, index);
540 #define BV_SIGNED_signed 1
541 #define BV_SIGNED_unsigned 0
542 #define INT16_T_signed scm_t_int16
543 #define INT16_T_unsigned scm_t_uint16
545 #define is_signed_int8(_x) (((_x) >= -128L) && ((_x) <= 127L))
546 #define is_unsigned_int8(_x) ((_x) <= 255UL)
547 #define is_signed_int16(_x) (((_x) >= -32768L) && ((_x) <= 32767L))
548 #define is_unsigned_int16(_x) ((_x) <= 65535UL)
550 /* Template of an integer reference function. */
551 #define INTEGER_REF(_sign) \
559 swap = !scm_is_eq (endianness, native_endianness); \
563 value = *(_sign char *) c_bv; \
566 value = *(INT16_T_ ## _sign *) c_bv; \
568 value = (INT16_T_ ## _sign) non_native_byteswap_16 (value); \
574 result = SCM_I_MAKINUM ((_sign int) value); \
577 result = bytevector_large_ref ((char *) c_bv, \
579 BV_SIGNED_ ## _sign, endianness); \
584 bytevector_signed_ref (const char *c_bv
, size_t c_size
, SCM endianness
)
586 INTEGER_REF (signed);
590 bytevector_unsigned_ref (const char *c_bv
, size_t c_size
, SCM endianness
)
592 INTEGER_REF (unsigned);
596 /* Template of an integer assignment function. */
597 #define INTEGER_SET(_sign) \
602 if (EXPECT_FALSE (!SCM_I_INUMP (value))) \
605 c_value = SCM_I_INUM (value); \
609 if (EXPECT_TRUE (is_ ## _sign ## _int8 (c_value))) \
610 * (_sign char *) c_bv = (_sign char) c_value; \
616 if (EXPECT_TRUE (is_ ## _sign ## _int16 (c_value))) \
619 INT16_T_ ## _sign c_value16; \
621 swap = !scm_is_eq (endianness, native_endianness); \
624 swap ? non_native_byteswap_16 (c_value) : c_value; \
625 *(INT16_T_ ## _sign *) c_bv = c_value16; \
639 err = bytevector_large_set (c_bv, c_size, \
640 BV_SIGNED_ ## _sign, \
641 value, endianness); \
649 scm_out_of_range (FUNC_NAME, value); \
653 bytevector_signed_set (char *c_bv
, size_t c_size
,
654 SCM value
, SCM endianness
,
655 const char *func_name
)
656 #define FUNC_NAME func_name
658 INTEGER_SET (signed);
663 bytevector_unsigned_set (char *c_bv
, size_t c_size
,
664 SCM value
, SCM endianness
,
665 const char *func_name
)
666 #define FUNC_NAME func_name
668 INTEGER_SET (unsigned);
674 #undef is_signed_int16
675 #undef is_unsigned_int16
676 #undef is_signed_int8
677 #undef is_unsigned_int8
678 #undef INT16_T_signed
679 #undef INT16_T_unsigned
680 #undef BV_SIGNED_unsigned
681 #undef BV_SIGNED_signed
684 SCM_DEFINE (scm_r6rs_bytevector_uint_ref
, "bytevector-uint-ref", 4, 0, 0,
685 (SCM bv
, SCM index
, SCM endianness
, SCM size
),
686 "Return the @var{size}-octet long unsigned integer at index "
687 "@var{index} in @var{bv}.")
688 #define FUNC_NAME s_scm_r6rs_bytevector_uint_ref
690 INTEGER_ACCESSOR_PROLOGUE ();
692 return (bytevector_unsigned_ref (&c_bv
[c_index
], c_size
, endianness
));
696 SCM_DEFINE (scm_r6rs_bytevector_sint_ref
, "bytevector-sint-ref", 4, 0, 0,
697 (SCM bv
, SCM index
, SCM endianness
, SCM size
),
698 "Return the @var{size}-octet long unsigned integer at index "
699 "@var{index} in @var{bv}.")
700 #define FUNC_NAME s_scm_r6rs_bytevector_sint_ref
702 INTEGER_ACCESSOR_PROLOGUE ();
704 return (bytevector_signed_ref (&c_bv
[c_index
], c_size
, endianness
));
708 SCM_DEFINE (scm_r6rs_bytevector_uint_set_x
, "bytevector-uint-set!", 5, 0, 0,
709 (SCM bv
, SCM index
, SCM value
, SCM endianness
, SCM size
),
710 "Set the @var{size}-octet long unsigned integer at @var{index} "
712 #define FUNC_NAME s_scm_r6rs_bytevector_uint_set_x
714 INTEGER_ACCESSOR_PROLOGUE ();
716 bytevector_unsigned_set (&c_bv
[c_index
], c_size
, value
, endianness
,
719 return SCM_UNSPECIFIED
;
723 SCM_DEFINE (scm_r6rs_bytevector_sint_set_x
, "bytevector-sint-set!", 5, 0, 0,
724 (SCM bv
, SCM index
, SCM value
, SCM endianness
, SCM size
),
725 "Set the @var{size}-octet long signed integer at @var{index} "
727 #define FUNC_NAME s_scm_r6rs_bytevector_sint_set_x
729 INTEGER_ACCESSOR_PROLOGUE ();
731 bytevector_signed_set (&c_bv
[c_index
], c_size
, value
, endianness
,
734 return SCM_UNSPECIFIED
;
740 /* Operations on integers of arbitrary size. */
742 #define INTEGERS_TO_LIST(_sign) \
745 size_t i, c_len, c_size; \
747 SCM_VALIDATE_R6RS_BYTEVECTOR (1, bv); \
748 SCM_VALIDATE_SYMBOL (2, endianness); \
749 c_size = scm_to_uint (size); \
751 c_bv = (char *) SCM_R6RS_BYTEVECTOR_CONTENTS (bv); \
752 c_len = SCM_R6RS_BYTEVECTOR_LENGTH (bv); \
754 lst = scm_make_list (scm_from_uint (c_len / c_size), SCM_UNSPECIFIED); \
755 for (i = 0, pair = lst; \
756 i <= c_len - c_size; \
757 i += c_size, c_bv += c_size, pair = SCM_CDR (pair)) \
760 bytevector_ ## _sign ## _ref (c_bv, c_size, \
766 SCM_DEFINE (scm_r6rs_bytevector_to_sint_list
, "bytevector->sint-list",
768 (SCM bv
, SCM endianness
, SCM size
),
769 "Return a list of signed integers of @var{size} octets "
770 "representing the contents of @var{bv}.")
771 #define FUNC_NAME s_scm_r6rs_bytevector_to_sint_list
773 INTEGERS_TO_LIST (signed);
777 SCM_DEFINE (scm_r6rs_bytevector_to_uint_list
, "bytevector->uint-list",
779 (SCM bv
, SCM endianness
, SCM size
),
780 "Return a list of unsigned integers of @var{size} octets "
781 "representing the contents of @var{bv}.")
782 #define FUNC_NAME s_scm_r6rs_bytevector_to_sint_list
784 INTEGERS_TO_LIST (unsigned);
788 #undef INTEGER_TO_LIST
791 #define INTEGER_LIST_TO_BYTEVECTOR(_sign) \
793 size_t c_len, c_size; \
794 char *c_bv, *c_bv_ptr; \
796 SCM_VALIDATE_LIST_COPYLEN (1, lst, c_len); \
797 SCM_VALIDATE_SYMBOL (2, endianness); \
798 c_size = scm_to_uint (size); \
800 if (EXPECT_FALSE ((c_size == 0) || (c_size >= (ULONG_MAX >> 3L)))) \
801 scm_out_of_range (FUNC_NAME, size); \
803 c_bv = scm_gc_malloc (c_len * c_size, SCM_GC_BYTEVECTOR); \
805 /* FIXME: We leak C_BV here if one of the elements in LST is incorrect \
806 but `scm_dynwind_free ()' isn't appropriate. */ \
808 for (c_bv_ptr = c_bv; \
809 !scm_is_null (lst); \
810 lst = SCM_CDR (lst), c_bv_ptr += c_size) \
812 bytevector_ ## _sign ## _set (c_bv_ptr, c_size, \
813 SCM_CAR (lst), endianness, \
817 result = make_bytevector (c_len * c_size, (signed char *) c_bv); \
822 SCM_DEFINE (scm_r6rs_uint_list_to_bytevector
, "uint-list->bytevector",
824 (SCM lst
, SCM endianness
, SCM size
),
825 "Return a bytevector containing the unsigned integers "
826 "listed in @var{lst} and encoded on @var{size} octets "
827 "according to @var{endianness}.")
828 #define FUNC_NAME s_scm_r6rs_uint_list_to_bytevector
830 INTEGER_LIST_TO_BYTEVECTOR (unsigned);
834 SCM_DEFINE (scm_r6rs_sint_list_to_bytevector
, "sint-list->bytevector",
836 (SCM lst
, SCM endianness
, SCM size
),
837 "Return a bytevector containing the signed integers "
838 "listed in @var{lst} and encoded on @var{size} octets "
839 "according to @var{endianness}.")
840 #define FUNC_NAME s_scm_r6rs_sint_list_to_bytevector
842 INTEGER_LIST_TO_BYTEVECTOR (signed);
846 #undef INTEGER_LIST_TO_BYTEVECTOR
849 /* FIXME: Unfinished! */
852 /* Initialization. */
855 scm_init_r6rs_bytevector (void)
857 #include "bytevector.c.x"
859 #ifdef WORDS_BIGENDIAN
860 native_endianness
= scm_sym_big
;
862 native_endianness
= scm_sym_little
;
866 /* arch-tag: e5a30664-90fc-40d7-8036-ee767aea5fb6