1 /* srfi-14.c --- SRFI-14 procedures for Guile
3 * Copyright (C) 2001, 2004, 2006, 2007 Free Software Foundation, Inc.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public License
7 * as published by the Free Software Foundation; either version 3 of
8 * the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
30 #include "libguile/srfi-14.h"
31 #include "libguile/strings.h"
32 #include "libguile/chars.h"
34 /* Include the pre-computed standard charset data. */
35 #include "libguile/srfi-14.i.c"
37 #define SCM_CHARSET_DATA(charset) ((scm_t_char_set *) SCM_SMOB_DATA (charset))
39 #define SCM_CHARSET_SET(cs, idx) \
40 scm_i_charset_set (SCM_CHARSET_DATA (cs), idx)
42 #define SCM_CHARSET_UNSET(cs, idx) \
43 scm_i_charset_unset (SCM_CHARSET_DATA (cs), idx)
45 /* Smob type code for character sets. */
46 int scm_tc16_charset
= 0;
47 int scm_tc16_charset_cursor
= 0;
49 /* True if N exists in charset CS. */
51 scm_i_charset_get (scm_t_char_set
*cs
, scm_t_wchar n
)
58 if (cs
->ranges
[i
].lo
<= n
&& n
<= cs
->ranges
[i
].hi
)
66 /* Put N into charset CS. */
68 scm_i_charset_set (scm_t_char_set
*cs
, scm_t_wchar n
)
78 /* Already in this range */
79 if (cs
->ranges
[i
].lo
<= n
&& n
<= cs
->ranges
[i
].hi
)
84 if (n
== cs
->ranges
[i
].lo
- 1)
86 /* This char is one below the current range. */
87 if (i
> 0 && cs
->ranges
[i
- 1].hi
+ 1 == n
)
89 /* It is also one above the previous range, so combine them. */
90 cs
->ranges
[i
- 1].hi
= cs
->ranges
[i
].hi
;
92 memmove (cs
->ranges
+ i
, cs
->ranges
+ (i
+ 1),
93 sizeof (scm_t_char_range
) * (len
- i
- 1));
94 cs
->ranges
= scm_gc_realloc (cs
->ranges
,
95 sizeof (scm_t_char_range
) * len
,
96 sizeof (scm_t_char_range
) * (len
-
104 /* Expand the range down by one. */
105 cs
->ranges
[i
].lo
= n
;
109 else if (n
== cs
->ranges
[i
].hi
+ 1)
111 /* This char is one above the current range. */
112 if (i
< len
- 1 && cs
->ranges
[i
+ 1].lo
- 1 == n
)
114 /* It is also one below the next range, so combine them. */
115 cs
->ranges
[i
].hi
= cs
->ranges
[i
+ 1].hi
;
117 memmove (cs
->ranges
+ (i
+ 1), cs
->ranges
+ (i
+ 2),
118 sizeof (scm_t_char_range
) * (len
- i
- 2));
119 cs
->ranges
= scm_gc_realloc (cs
->ranges
,
120 sizeof (scm_t_char_range
) * len
,
121 sizeof (scm_t_char_range
) * (len
-
129 /* Expand the range up by one. */
130 cs
->ranges
[i
].hi
= n
;
134 else if (n
< cs
->ranges
[i
].lo
- 1)
136 /* This is a new range below the current one. */
137 cs
->ranges
= scm_gc_realloc (cs
->ranges
,
138 sizeof (scm_t_char_range
) * len
,
139 sizeof (scm_t_char_range
) * (len
+ 1),
141 memmove (cs
->ranges
+ (i
+ 1), cs
->ranges
+ i
,
142 sizeof (scm_t_char_range
) * (len
- i
));
143 cs
->ranges
[i
].lo
= n
;
144 cs
->ranges
[i
].hi
= n
;
152 /* This is a new range above all previous ranges. */
155 cs
->ranges
= scm_gc_malloc (sizeof (scm_t_char_range
), "character-set");
159 cs
->ranges
= scm_gc_realloc (cs
->ranges
,
160 sizeof (scm_t_char_range
) * len
,
161 sizeof (scm_t_char_range
) * (len
+ 1),
164 cs
->ranges
[len
].lo
= n
;
165 cs
->ranges
[len
].hi
= n
;
171 /* Put LO to HI inclusive into charset CS. */
173 scm_i_charset_set_range (scm_t_char_set
*cs
, scm_t_wchar lo
, scm_t_wchar hi
)
180 /* Already in this range */
181 if (cs
->ranges
[i
].lo
<= lo
&& cs
->ranges
[i
].hi
>= hi
)
187 if (cs
->ranges
[i
].lo
- 1 > hi
)
189 /* Add a new range below the current one. */
190 cs
->ranges
= scm_gc_realloc (cs
->ranges
,
191 sizeof (scm_t_char_range
) * cs
->len
,
192 sizeof (scm_t_char_range
) * (cs
->len
+ 1),
194 memmove (cs
->ranges
+ (i
+ 1), cs
->ranges
+ i
,
195 sizeof (scm_t_char_range
) * (cs
->len
- i
));
196 cs
->ranges
[i
].lo
= lo
;
197 cs
->ranges
[i
].hi
= hi
;
202 /* cur: +---+ or +---+ or +---+
203 new: +---+ +---+ +---+
205 if (cs
->ranges
[i
].lo
> lo
206 && (cs
->ranges
[i
].lo
- 1 <= hi
&& cs
->ranges
[i
].hi
>= hi
))
208 cs
->ranges
[i
].lo
= lo
;
212 /* cur: +---+ or +---+ or +---+
213 new: +---+ +---+ +---+
215 else if (cs
->ranges
[i
].hi
+ 1 >= lo
&& cs
->ranges
[i
].hi
< hi
)
217 if (cs
->ranges
[i
].lo
> lo
)
218 cs
->ranges
[i
].lo
= lo
;
219 if (cs
->ranges
[i
].hi
< hi
)
220 cs
->ranges
[i
].hi
= hi
;
221 while (i
< cs
->len
- 1)
226 if (cs
->ranges
[i
+ 1].lo
- 1 > hi
)
229 /* cur: --+ +---+ or --+ +---+ or --+ +--+
230 new: -----+ ------+ ---------+
232 /* Combine this range with the previous one. */
233 if (cs
->ranges
[i
+ 1].hi
> hi
)
234 cs
->ranges
[i
].hi
= cs
->ranges
[i
+ 1].hi
;
236 memmove (cs
->ranges
+ i
+ 1, cs
->ranges
+ i
+ 2,
237 sizeof (scm_t_char_range
) * (cs
->len
- i
- 2));
238 cs
->ranges
= scm_gc_realloc (cs
->ranges
,
239 sizeof (scm_t_char_range
) * cs
->len
,
240 sizeof (scm_t_char_range
) * (cs
->len
- 1),
249 /* This is a new range above all previous ranges. */
252 cs
->ranges
= scm_gc_malloc (sizeof (scm_t_char_range
), "character-set");
256 cs
->ranges
= scm_gc_realloc (cs
->ranges
,
257 sizeof (scm_t_char_range
) * cs
->len
,
258 sizeof (scm_t_char_range
) * (cs
->len
+ 1),
262 cs
->ranges
[cs
->len
- 1].lo
= lo
;
263 cs
->ranges
[cs
->len
- 1].hi
= hi
;
268 /* If N is in charset CS, remove it. */
270 scm_i_charset_unset (scm_t_char_set
*cs
, scm_t_wchar n
)
280 if (n
< cs
->ranges
[i
].lo
)
281 /* Not in this set. */
284 if (n
== cs
->ranges
[i
].lo
&& n
== cs
->ranges
[i
].hi
)
286 /* Remove this one-character range. */
289 scm_gc_free (cs
->ranges
,
290 sizeof (scm_t_char_range
) * cs
->len
,
296 else if (i
< len
- 1)
298 memmove (cs
->ranges
+ i
, cs
->ranges
+ (i
+ 1),
299 sizeof (scm_t_char_range
) * (len
- i
- 1));
300 cs
->ranges
= scm_gc_realloc (cs
->ranges
,
301 sizeof (scm_t_char_range
) * len
,
302 sizeof (scm_t_char_range
) * (len
-
308 else if (i
== len
- 1)
310 cs
->ranges
= scm_gc_realloc (cs
->ranges
,
311 sizeof (scm_t_char_range
) * len
,
312 sizeof (scm_t_char_range
) * (len
-
319 else if (n
== cs
->ranges
[i
].lo
)
321 /* Shrink this range from the left. */
322 cs
->ranges
[i
].lo
= n
+ 1;
325 else if (n
== cs
->ranges
[i
].hi
)
327 /* Shrink this range from the right. */
328 cs
->ranges
[i
].hi
= n
- 1;
331 else if (n
> cs
->ranges
[i
].lo
&& n
< cs
->ranges
[i
].hi
)
333 /* Split this range into two pieces. */
334 cs
->ranges
= scm_gc_realloc (cs
->ranges
,
335 sizeof (scm_t_char_range
) * len
,
336 sizeof (scm_t_char_range
) * (len
+ 1),
339 memmove (cs
->ranges
+ (i
+ 2), cs
->ranges
+ (i
+ 1),
340 sizeof (scm_t_char_range
) * (len
- i
- 1));
341 cs
->ranges
[i
+ 1].hi
= cs
->ranges
[i
].hi
;
342 cs
->ranges
[i
+ 1].lo
= n
+ 1;
343 cs
->ranges
[i
].hi
= n
- 1;
351 /* This value is above all ranges, so do nothing here. */
356 charsets_equal (scm_t_char_set
*a
, scm_t_char_set
*b
)
358 if (a
->len
!= b
->len
)
361 if (memcmp (a
->ranges
, b
->ranges
, sizeof (scm_t_char_range
) * a
->len
) != 0)
367 /* Return true if every character in A is also in B. */
369 charsets_leq (scm_t_char_set
*a
, scm_t_char_set
*b
)
372 scm_t_wchar alo
, ahi
;
380 alo
= a
->ranges
[i
].lo
;
381 ahi
= a
->ranges
[i
].hi
;
382 while (b
->ranges
[j
].hi
< alo
)
389 if (alo
< b
->ranges
[j
].lo
|| ahi
> b
->ranges
[j
].hi
)
397 /* Merge B into A. */
399 charsets_union (scm_t_char_set
*a
, scm_t_char_set
*b
)
402 scm_t_wchar blo
, bhi
, n
;
410 a
->ranges
= scm_gc_malloc (sizeof (scm_t_char_range
) * b
->len
,
412 memcpy (a
->ranges
, b
->ranges
, sizeof (scm_t_char_range
) * b
->len
);
416 /* This needs optimization. */
419 blo
= b
->ranges
[i
].lo
;
420 bhi
= b
->ranges
[i
].hi
;
421 for (n
= blo
; n
<= bhi
; n
++)
422 scm_i_charset_set (a
, n
);
430 /* Remove elements not both in A and B from A. */
432 charsets_intersection (scm_t_char_set
*a
, scm_t_char_set
*b
)
435 scm_t_wchar blo
, bhi
, n
;
443 scm_gc_free (a
->ranges
, sizeof (scm_t_char_range
) * a
->len
,
449 c
= (scm_t_char_set
*) scm_malloc (sizeof (scm_t_char_set
));
455 blo
= b
->ranges
[i
].lo
;
456 bhi
= b
->ranges
[i
].hi
;
457 for (n
= blo
; n
<= bhi
; n
++)
458 if (scm_i_charset_get (a
, n
))
459 scm_i_charset_set (c
, n
);
462 scm_gc_free (a
->ranges
, sizeof (scm_t_char_range
) * a
->len
,
467 a
->ranges
= c
->ranges
;
474 /* Make P the compelement of Q. */
476 charsets_complement (scm_t_char_set
*p
, scm_t_char_set
*q
)
482 /* Fill with all valid codepoints. */
484 p
->ranges
= scm_gc_malloc (sizeof (scm_t_char_range
) * 2,
487 p
->ranges
[0].hi
= SCM_CODEPOINT_SURROGATE_START
- 1;
488 p
->ranges
[1].lo
= SCM_CODEPOINT_SURROGATE_END
+ 1;
489 p
->ranges
[1].hi
= SCM_CODEPOINT_MAX
;
494 scm_gc_free (p
->ranges
, sizeof (scm_t_char_set
) * p
->len
,
498 if (q
->ranges
[0].lo
> 0)
500 if (q
->ranges
[q
->len
- 1].hi
< SCM_CODEPOINT_MAX
)
502 p
->len
+= q
->len
- 1;
504 (scm_t_char_range
*) scm_gc_malloc (sizeof (scm_t_char_range
) * p
->len
,
507 if (q
->ranges
[0].lo
> 0)
509 p
->ranges
[idx
].lo
= 0;
510 p
->ranges
[idx
++].hi
= q
->ranges
[0].lo
- 1;
512 for (k
= 1; k
< q
->len
; k
++)
514 p
->ranges
[idx
].lo
= q
->ranges
[k
- 1].hi
+ 1;
515 p
->ranges
[idx
++].hi
= q
->ranges
[k
].lo
- 1;
517 if (q
->ranges
[q
->len
- 1].hi
< SCM_CODEPOINT_MAX
)
519 p
->ranges
[idx
].lo
= q
->ranges
[q
->len
- 1].hi
+ 1;
520 p
->ranges
[idx
].hi
= SCM_CODEPOINT_MAX
;
525 /* Replace A with elements only found in one of A or B. */
527 charsets_xor (scm_t_char_set
*a
, scm_t_char_set
*b
)
530 scm_t_wchar blo
, bhi
, n
;
540 (scm_t_char_range
*) scm_gc_malloc (sizeof (scm_t_char_range
) *
541 b
->len
, "character-set");
543 memcpy (a
->ranges
, b
->ranges
, sizeof (scm_t_char_range
) * a
->len
);
549 blo
= b
->ranges
[i
].lo
;
550 bhi
= b
->ranges
[i
].hi
;
551 for (n
= blo
; n
<= bhi
; n
++)
553 if (scm_i_charset_get (a
, n
))
554 scm_i_charset_unset (a
, n
);
556 scm_i_charset_set (a
, n
);
564 /* Smob print hook for character sets. */
566 charset_print (SCM charset
, SCM port
, scm_print_state
*pstate SCM_UNUSED
)
571 const size_t max_ranges_to_print
= 50;
573 p
= SCM_CHARSET_DATA (charset
);
575 scm_puts ("#<charset {", port
);
576 for (i
= 0; i
< p
->len
; i
++)
581 scm_puts (" ", port
);
582 scm_write (SCM_MAKE_CHAR (p
->ranges
[i
].lo
), port
);
583 if (p
->ranges
[i
].lo
!= p
->ranges
[i
].hi
)
585 scm_puts ("..", port
);
586 scm_write (SCM_MAKE_CHAR (p
->ranges
[i
].hi
), port
);
588 if (i
>= max_ranges_to_print
)
590 /* Too many to print here. Quit early. */
591 scm_puts (" ...", port
);
595 scm_puts ("}>", port
);
600 /* Smob free hook for character sets. */
602 charset_free (SCM charset
)
607 cs
= SCM_CHARSET_DATA (charset
);
611 scm_gc_free (cs
->ranges
, sizeof (scm_t_char_range
) * len
,
617 scm_gc_free (cs
, sizeof (scm_t_char_set
), "character-set");
619 scm_remember_upto_here_1 (charset
);
625 /* Smob print hook for character sets cursors. */
627 charset_cursor_print (SCM cursor
, SCM port
,
628 scm_print_state
*pstate SCM_UNUSED
)
630 scm_t_char_set_cursor
*cur
;
632 cur
= (scm_t_char_set_cursor
*) SCM_SMOB_DATA (cursor
);
634 scm_puts ("#<charset-cursor ", port
);
635 if (cur
->range
== (size_t) (-1))
636 scm_puts ("(empty)", port
);
639 scm_write (scm_from_size_t (cur
->range
), port
);
640 scm_puts (":", port
);
641 scm_write (scm_from_int32 (cur
->n
), port
);
643 scm_puts (">", port
);
647 /* Smob free hook for character sets. */
649 charset_cursor_free (SCM charset
)
651 scm_t_char_set_cursor
*cur
;
653 cur
= (scm_t_char_set_cursor
*) SCM_SMOB_DATA (charset
);
654 scm_gc_free (cur
, sizeof (scm_t_char_set_cursor
), "charset-cursor");
655 scm_remember_upto_here_1 (charset
);
661 /* Create a new, empty character set. */
663 make_char_set (const char *func_name
)
667 p
= scm_gc_malloc (sizeof (scm_t_char_set
), "character-set");
668 memset (p
, 0, sizeof (scm_t_char_set
));
669 SCM_RETURN_NEWSMOB (scm_tc16_charset
, p
);
673 SCM_DEFINE (scm_char_set_p
, "char-set?", 1, 0, 0,
675 "Return @code{#t} if @var{obj} is a character set, @code{#f}\n"
677 #define FUNC_NAME s_scm_char_set_p
679 return scm_from_bool (SCM_SMOB_PREDICATE (scm_tc16_charset
, obj
));
684 SCM_DEFINE (scm_char_set_eq
, "char-set=", 0, 0, 1,
686 "Return @code{#t} if all given character sets are equal.")
687 #define FUNC_NAME s_scm_char_set_eq
690 scm_t_char_set
*cs1_data
= NULL
;
692 SCM_VALIDATE_REST_ARGUMENT (char_sets
);
694 while (!scm_is_null (char_sets
))
696 SCM csi
= SCM_CAR (char_sets
);
697 scm_t_char_set
*csi_data
;
699 SCM_VALIDATE_SMOB (argnum
, csi
, charset
);
701 csi_data
= SCM_CHARSET_DATA (csi
);
702 if (cs1_data
== NULL
)
704 else if (!charsets_equal (cs1_data
, csi_data
))
706 char_sets
= SCM_CDR (char_sets
);
713 SCM_DEFINE (scm_char_set_leq
, "char-set<=", 0, 0, 1,
715 "Return @code{#t} if every character set @var{cs}i is a subset\n"
716 "of character set @var{cs}i+1.")
717 #define FUNC_NAME s_scm_char_set_leq
720 scm_t_char_set
*prev_data
= NULL
;
722 SCM_VALIDATE_REST_ARGUMENT (char_sets
);
724 while (!scm_is_null (char_sets
))
726 SCM csi
= SCM_CAR (char_sets
);
727 scm_t_char_set
*csi_data
;
729 SCM_VALIDATE_SMOB (argnum
, csi
, charset
);
731 csi_data
= SCM_CHARSET_DATA (csi
);
734 if (!charsets_leq (prev_data
, csi_data
))
737 prev_data
= csi_data
;
738 char_sets
= SCM_CDR (char_sets
);
745 SCM_DEFINE (scm_char_set_hash
, "char-set-hash", 1, 1, 0,
747 "Compute a hash value for the character set @var{cs}. If\n"
748 "@var{bound} is given and non-zero, it restricts the\n"
749 "returned value to the range 0 @dots{} @var{bound - 1}.")
750 #define FUNC_NAME s_scm_char_set_hash
752 const unsigned long default_bnd
= 871;
755 unsigned long val
= 0;
759 SCM_VALIDATE_SMOB (1, cs
, charset
);
761 if (SCM_UNBNDP (bound
))
765 bnd
= scm_to_ulong (bound
);
770 p
= SCM_CHARSET_DATA (cs
);
771 for (k
= 0; k
< p
->len
; k
++)
773 for (c
= p
->ranges
[k
].lo
; c
<= p
->ranges
[k
].hi
; c
++)
774 val
= c
+ (val
<< 1);
776 return scm_from_ulong (val
% bnd
);
781 SCM_DEFINE (scm_char_set_cursor
, "char-set-cursor", 1, 0, 0,
782 (SCM cs
), "Return a cursor into the character set @var{cs}.")
783 #define FUNC_NAME s_scm_char_set_cursor
785 scm_t_char_set
*cs_data
;
786 scm_t_char_set_cursor
*cur_data
;
788 SCM_VALIDATE_SMOB (1, cs
, charset
);
789 cs_data
= SCM_CHARSET_DATA (cs
);
791 (scm_t_char_set_cursor
*) scm_gc_malloc (sizeof (scm_t_char_set_cursor
),
793 if (cs_data
->len
== 0)
795 cur_data
->range
= (size_t) (-1);
801 cur_data
->n
= cs_data
->ranges
[0].lo
;
803 SCM_RETURN_NEWSMOB (scm_tc16_charset_cursor
, cur_data
);
808 SCM_DEFINE (scm_char_set_ref
, "char-set-ref", 2, 0, 0,
809 (SCM cs
, SCM cursor
),
810 "Return the character at the current cursor position\n"
811 "@var{cursor} in the character set @var{cs}. It is an error to\n"
812 "pass a cursor for which @code{end-of-char-set?} returns true.")
813 #define FUNC_NAME s_scm_char_set_ref
815 scm_t_char_set
*cs_data
;
816 scm_t_char_set_cursor
*cur_data
;
819 SCM_VALIDATE_SMOB (1, cs
, charset
);
820 SCM_VALIDATE_SMOB (2, cursor
, charset_cursor
);
822 cs_data
= SCM_CHARSET_DATA (cs
);
823 cur_data
= (scm_t_char_set_cursor
*) SCM_SMOB_DATA (cursor
);
825 /* Validate that this cursor is still true. */
827 if (i
== (size_t) (-1)
829 || cur_data
->n
< cs_data
->ranges
[i
].lo
830 || cur_data
->n
> cs_data
->ranges
[i
].hi
)
831 SCM_MISC_ERROR ("invalid character set cursor: ~A", scm_list_1 (cursor
));
832 return SCM_MAKE_CHAR (cur_data
->n
);
837 SCM_DEFINE (scm_char_set_cursor_next
, "char-set-cursor-next", 2, 0, 0,
838 (SCM cs
, SCM cursor
),
839 "Advance the character set cursor @var{cursor} to the next\n"
840 "character in the character set @var{cs}. It is an error if the\n"
841 "cursor given satisfies @code{end-of-char-set?}.")
842 #define FUNC_NAME s_scm_char_set_cursor_next
844 scm_t_char_set
*cs_data
;
845 scm_t_char_set_cursor
*cur_data
;
848 SCM_VALIDATE_SMOB (1, cs
, charset
);
849 SCM_VALIDATE_SMOB (2, cursor
, charset_cursor
);
851 cs_data
= SCM_CHARSET_DATA (cs
);
852 cur_data
= (scm_t_char_set_cursor
*) SCM_SMOB_DATA (cursor
);
854 /* Validate that this cursor is still true. */
856 if (i
== (size_t) (-1)
858 || cur_data
->n
< cs_data
->ranges
[i
].lo
859 || cur_data
->n
> cs_data
->ranges
[i
].hi
)
860 SCM_MISC_ERROR ("invalid character set cursor: ~A", scm_list_1 (cursor
));
861 /* Increment the cursor. */
862 if (cur_data
->n
== cs_data
->ranges
[i
].hi
)
864 if (i
+ 1 < cs_data
->len
)
866 cur_data
->range
= i
+ 1;
867 cur_data
->n
= cs_data
->ranges
[i
+ 1].lo
;
871 /* This is the end of the road. */
872 cur_data
->range
= (size_t) (-1);
878 cur_data
->n
= cur_data
->n
+ 1;
886 SCM_DEFINE (scm_end_of_char_set_p
, "end-of-char-set?", 1, 0, 0,
888 "Return @code{#t} if @var{cursor} has reached the end of a\n"
889 "character set, @code{#f} otherwise.")
890 #define FUNC_NAME s_scm_end_of_char_set_p
892 scm_t_char_set_cursor
*cur_data
;
893 SCM_VALIDATE_SMOB (1, cursor
, charset_cursor
);
895 cur_data
= (scm_t_char_set_cursor
*) SCM_SMOB_DATA (cursor
);
896 if (cur_data
->range
== (size_t) (-1))
904 SCM_DEFINE (scm_char_set_fold
, "char-set-fold", 3, 0, 0,
905 (SCM kons
, SCM knil
, SCM cs
),
906 "Fold the procedure @var{kons} over the character set @var{cs},\n"
907 "initializing it with @var{knil}.")
908 #define FUNC_NAME s_scm_char_set_fold
910 scm_t_char_set
*cs_data
;
914 SCM_VALIDATE_PROC (1, kons
);
915 SCM_VALIDATE_SMOB (3, cs
, charset
);
917 cs_data
= SCM_CHARSET_DATA (cs
);
919 if (cs_data
->len
== 0)
922 for (k
= 0; k
< cs_data
->len
; k
++)
923 for (n
= cs_data
->ranges
[k
].lo
; n
<= cs_data
->ranges
[k
].hi
; n
++)
925 knil
= scm_call_2 (kons
, SCM_MAKE_CHAR (n
), knil
);
932 SCM_DEFINE (scm_char_set_unfold
, "char-set-unfold", 4, 1, 0,
933 (SCM p
, SCM f
, SCM g
, SCM seed
, SCM base_cs
),
934 "This is a fundamental constructor for character sets.\n"
936 "@item @var{g} is used to generate a series of ``seed'' values\n"
937 "from the initial seed: @var{seed}, (@var{g} @var{seed}),\n"
938 "(@var{g}^2 @var{seed}), (@var{g}^3 @var{seed}), @dots{}\n"
939 "@item @var{p} tells us when to stop -- when it returns true\n"
940 "when applied to one of the seed values.\n"
941 "@item @var{f} maps each seed value to a character. These\n"
942 "characters are added to the base character set @var{base_cs} to\n"
943 "form the result; @var{base_cs} defaults to the empty set.\n"
945 #define FUNC_NAME s_scm_char_set_unfold
949 SCM_VALIDATE_PROC (1, p
);
950 SCM_VALIDATE_PROC (2, f
);
951 SCM_VALIDATE_PROC (3, g
);
952 if (!SCM_UNBNDP (base_cs
))
954 SCM_VALIDATE_SMOB (5, base_cs
, charset
);
955 result
= scm_char_set_copy (base_cs
);
958 result
= make_char_set (FUNC_NAME
);
960 tmp
= scm_call_1 (p
, seed
);
961 while (scm_is_false (tmp
))
963 SCM ch
= scm_call_1 (f
, seed
);
965 SCM_MISC_ERROR ("procedure ~S returned non-char", scm_list_1 (f
));
966 SCM_CHARSET_SET (result
, SCM_CHAR (ch
));
968 seed
= scm_call_1 (g
, seed
);
969 tmp
= scm_call_1 (p
, seed
);
976 SCM_DEFINE (scm_char_set_unfold_x
, "char-set-unfold!", 5, 0, 0,
977 (SCM p
, SCM f
, SCM g
, SCM seed
, SCM base_cs
),
978 "This is a fundamental constructor for character sets.\n"
980 "@item @var{g} is used to generate a series of ``seed'' values\n"
981 "from the initial seed: @var{seed}, (@var{g} @var{seed}),\n"
982 "(@var{g}^2 @var{seed}), (@var{g}^3 @var{seed}), @dots{}\n"
983 "@item @var{p} tells us when to stop -- when it returns true\n"
984 "when applied to one of the seed values.\n"
985 "@item @var{f} maps each seed value to a character. These\n"
986 "characters are added to the base character set @var{base_cs} to\n"
987 "form the result; @var{base_cs} defaults to the empty set.\n"
989 #define FUNC_NAME s_scm_char_set_unfold_x
993 SCM_VALIDATE_PROC (1, p
);
994 SCM_VALIDATE_PROC (2, f
);
995 SCM_VALIDATE_PROC (3, g
);
996 SCM_VALIDATE_SMOB (5, base_cs
, charset
);
998 tmp
= scm_call_1 (p
, seed
);
999 while (scm_is_false (tmp
))
1001 SCM ch
= scm_call_1 (f
, seed
);
1002 if (!SCM_CHARP (ch
))
1003 SCM_MISC_ERROR ("procedure ~S returned non-char", scm_list_1 (f
));
1004 SCM_CHARSET_SET (base_cs
, SCM_CHAR (ch
));
1006 seed
= scm_call_1 (g
, seed
);
1007 tmp
= scm_call_1 (p
, seed
);
1014 SCM_DEFINE (scm_char_set_for_each
, "char-set-for-each", 2, 0, 0,
1016 "Apply @var{proc} to every character in the character set\n"
1017 "@var{cs}. The return value is not specified.")
1018 #define FUNC_NAME s_scm_char_set_for_each
1020 scm_t_char_set
*cs_data
;
1024 SCM_VALIDATE_PROC (1, proc
);
1025 SCM_VALIDATE_SMOB (2, cs
, charset
);
1027 cs_data
= SCM_CHARSET_DATA (cs
);
1029 if (cs_data
->len
== 0)
1030 return SCM_UNSPECIFIED
;
1032 for (k
= 0; k
< cs_data
->len
; k
++)
1033 for (n
= cs_data
->ranges
[k
].lo
; n
<= cs_data
->ranges
[k
].hi
; n
++)
1035 scm_call_1 (proc
, SCM_MAKE_CHAR (n
));
1038 return SCM_UNSPECIFIED
;
1043 SCM_DEFINE (scm_char_set_map
, "char-set-map", 2, 0, 0,
1045 "Map the procedure @var{proc} over every character in @var{cs}.\n"
1046 "@var{proc} must be a character -> character procedure.")
1047 #define FUNC_NAME s_scm_char_set_map
1051 scm_t_char_set
*cs_data
;
1054 SCM_VALIDATE_PROC (1, proc
);
1055 SCM_VALIDATE_SMOB (2, cs
, charset
);
1057 result
= make_char_set (FUNC_NAME
);
1058 cs_data
= SCM_CHARSET_DATA (cs
);
1060 if (cs_data
->len
== 0)
1063 for (k
= 0; k
< cs_data
->len
; k
++)
1064 for (n
= cs_data
->ranges
[k
].lo
; n
<= cs_data
->ranges
[k
].hi
; n
++)
1066 SCM ch
= scm_call_1 (proc
, SCM_MAKE_CHAR (n
));
1067 if (!SCM_CHARP (ch
))
1068 SCM_MISC_ERROR ("procedure ~S returned non-char",
1070 SCM_CHARSET_SET (result
, SCM_CHAR (ch
));
1077 SCM_DEFINE (scm_char_set_copy
, "char-set-copy", 1, 0, 0,
1079 "Return a newly allocated character set containing all\n"
1080 "characters in @var{cs}.")
1081 #define FUNC_NAME s_scm_char_set_copy
1084 scm_t_char_set
*p1
, *p2
;
1086 SCM_VALIDATE_SMOB (1, cs
, charset
);
1087 ret
= make_char_set (FUNC_NAME
);
1088 p1
= SCM_CHARSET_DATA (cs
);
1089 p2
= SCM_CHARSET_DATA (ret
);
1096 p2
->ranges
= scm_gc_malloc (sizeof (scm_t_char_range
) * p1
->len
,
1098 memcpy (p2
->ranges
, p1
->ranges
, sizeof (scm_t_char_range
) * p1
->len
);
1106 SCM_DEFINE (scm_char_set
, "char-set", 0, 0, 1,
1108 "Return a character set containing all given characters.")
1109 #define FUNC_NAME s_scm_char_set
1114 SCM_VALIDATE_REST_ARGUMENT (rest
);
1115 cs
= make_char_set (FUNC_NAME
);
1116 while (!scm_is_null (rest
))
1120 SCM_VALIDATE_CHAR_COPY (argnum
, SCM_CAR (rest
), c
);
1122 rest
= SCM_CDR (rest
);
1123 SCM_CHARSET_SET (cs
, c
);
1130 SCM_DEFINE (scm_list_to_char_set
, "list->char-set", 1, 1, 0,
1131 (SCM list
, SCM base_cs
),
1132 "Convert the character list @var{list} to a character set. If\n"
1133 "the character set @var{base_cs} is given, the character in this\n"
1134 "set are also included in the result.")
1135 #define FUNC_NAME s_scm_list_to_char_set
1139 SCM_VALIDATE_LIST (1, list
);
1140 if (SCM_UNBNDP (base_cs
))
1141 cs
= make_char_set (FUNC_NAME
);
1144 SCM_VALIDATE_SMOB (2, base_cs
, charset
);
1145 cs
= scm_char_set_copy (base_cs
);
1147 while (!scm_is_null (list
))
1149 SCM chr
= SCM_CAR (list
);
1152 SCM_VALIDATE_CHAR_COPY (0, chr
, c
);
1153 list
= SCM_CDR (list
);
1156 SCM_CHARSET_SET (cs
, c
);
1163 SCM_DEFINE (scm_list_to_char_set_x
, "list->char-set!", 2, 0, 0,
1164 (SCM list
, SCM base_cs
),
1165 "Convert the character list @var{list} to a character set. The\n"
1166 "characters are added to @var{base_cs} and @var{base_cs} is\n"
1168 #define FUNC_NAME s_scm_list_to_char_set_x
1170 SCM_VALIDATE_LIST (1, list
);
1171 SCM_VALIDATE_SMOB (2, base_cs
, charset
);
1172 while (!scm_is_null (list
))
1174 SCM chr
= SCM_CAR (list
);
1177 SCM_VALIDATE_CHAR_COPY (0, chr
, c
);
1178 list
= SCM_CDR (list
);
1180 SCM_CHARSET_SET (base_cs
, c
);
1187 SCM_DEFINE (scm_string_to_char_set
, "string->char-set", 1, 1, 0,
1188 (SCM str
, SCM base_cs
),
1189 "Convert the string @var{str} to a character set. If the\n"
1190 "character set @var{base_cs} is given, the characters in this\n"
1191 "set are also included in the result.")
1192 #define FUNC_NAME s_scm_string_to_char_set
1197 SCM_VALIDATE_STRING (1, str
);
1198 if (SCM_UNBNDP (base_cs
))
1199 cs
= make_char_set (FUNC_NAME
);
1202 SCM_VALIDATE_SMOB (2, base_cs
, charset
);
1203 cs
= scm_char_set_copy (base_cs
);
1205 len
= scm_i_string_length (str
);
1208 scm_t_wchar c
= scm_i_string_ref (str
, k
++);
1209 SCM_CHARSET_SET (cs
, c
);
1211 scm_remember_upto_here_1 (str
);
1217 SCM_DEFINE (scm_string_to_char_set_x
, "string->char-set!", 2, 0, 0,
1218 (SCM str
, SCM base_cs
),
1219 "Convert the string @var{str} to a character set. The\n"
1220 "characters from the string are added to @var{base_cs}, and\n"
1221 "@var{base_cs} is returned.")
1222 #define FUNC_NAME s_scm_string_to_char_set_x
1226 SCM_VALIDATE_STRING (1, str
);
1227 SCM_VALIDATE_SMOB (2, base_cs
, charset
);
1228 len
= scm_i_string_length (str
);
1231 scm_t_wchar c
= scm_i_string_ref (str
, k
++);
1232 SCM_CHARSET_SET (base_cs
, c
);
1234 scm_remember_upto_here_1 (str
);
1240 SCM_DEFINE (scm_char_set_filter
, "char-set-filter", 2, 1, 0,
1241 (SCM pred
, SCM cs
, SCM base_cs
),
1242 "Return a character set containing every character from @var{cs}\n"
1243 "so that it satisfies @var{pred}. If provided, the characters\n"
1244 "from @var{base_cs} are added to the result.")
1245 #define FUNC_NAME s_scm_char_set_filter
1252 SCM_VALIDATE_PROC (1, pred
);
1253 SCM_VALIDATE_SMOB (2, cs
, charset
);
1254 if (!SCM_UNBNDP (base_cs
))
1256 SCM_VALIDATE_SMOB (3, base_cs
, charset
);
1257 ret
= scm_char_set_copy (base_cs
);
1260 ret
= make_char_set (FUNC_NAME
);
1262 p
= SCM_CHARSET_DATA (cs
);
1267 for (k
= 0; k
< p
->len
; k
++)
1268 for (n
= p
->ranges
[k
].lo
; n
<= p
->ranges
[k
].hi
; n
++)
1270 SCM res
= scm_call_1 (pred
, SCM_MAKE_CHAR (n
));
1272 if (scm_is_true (res
))
1273 SCM_CHARSET_SET (ret
, n
);
1280 SCM_DEFINE (scm_char_set_filter_x
, "char-set-filter!", 3, 0, 0,
1281 (SCM pred
, SCM cs
, SCM base_cs
),
1282 "Return a character set containing every character from @var{cs}\n"
1283 "so that it satisfies @var{pred}. The characters are added to\n"
1284 "@var{base_cs} and @var{base_cs} is returned.")
1285 #define FUNC_NAME s_scm_char_set_filter_x
1291 SCM_VALIDATE_PROC (1, pred
);
1292 SCM_VALIDATE_SMOB (2, cs
, charset
);
1293 SCM_VALIDATE_SMOB (3, base_cs
, charset
);
1294 p
= SCM_CHARSET_DATA (cs
);
1298 for (k
= 0; k
< p
->len
; k
++)
1299 for (n
= p
->ranges
[k
].lo
; n
<= p
->ranges
[k
].hi
; n
++)
1301 SCM res
= scm_call_1 (pred
, SCM_MAKE_CHAR (n
));
1303 if (scm_is_true (res
))
1304 SCM_CHARSET_SET (base_cs
, n
);
1311 /* Return a character set containing all the characters from [LOWER,UPPER),
1312 giving range errors if ERROR, adding chars from BASE_CS, and recycling
1313 BASE_CS if REUSE is true. */
1315 scm_i_ucs_range_to_char_set (const char *FUNC_NAME
, SCM lower
, SCM upper
,
1316 SCM error
, SCM base_cs
, int reuse
)
1319 size_t clower
, cupper
;
1321 clower
= scm_to_size_t (lower
);
1322 cupper
= scm_to_size_t (upper
) - 1;
1323 SCM_ASSERT_RANGE (1, lower
, clower
>= 0);
1324 SCM_ASSERT_RANGE (2, upper
, cupper
>= 0);
1325 SCM_ASSERT_RANGE (2, upper
, cupper
>= clower
);
1326 if (!SCM_UNBNDP (error
))
1328 if (scm_is_true (error
))
1330 SCM_ASSERT_RANGE (1, lower
, SCM_IS_UNICODE_CHAR (clower
));
1331 SCM_ASSERT_RANGE (2, upper
, SCM_IS_UNICODE_CHAR (cupper
));
1332 if (clower
< SCM_CODEPOINT_SURROGATE_START
1333 && cupper
> SCM_CODEPOINT_SURROGATE_END
)
1334 scm_error(scm_out_of_range_key
,
1335 FUNC_NAME
, "invalid range - contains surrogate characters: ~S to ~S",
1336 scm_list_2 (lower
, upper
), scm_list_1 (upper
));
1340 if (SCM_UNBNDP (base_cs
))
1341 cs
= make_char_set (FUNC_NAME
);
1344 SCM_VALIDATE_SMOB (4, base_cs
, charset
);
1348 cs
= scm_char_set_copy (base_cs
);
1351 if ((clower
>= SCM_CODEPOINT_SURROGATE_START
&& clower
<= SCM_CODEPOINT_SURROGATE_END
)
1352 && (cupper
>= SCM_CODEPOINT_SURROGATE_START
&& cupper
<= SCM_CODEPOINT_SURROGATE_END
))
1355 if (clower
> SCM_CODEPOINT_MAX
)
1356 clower
= SCM_CODEPOINT_MAX
;
1357 if (clower
>= SCM_CODEPOINT_SURROGATE_START
&& clower
<= SCM_CODEPOINT_SURROGATE_END
)
1358 clower
= SCM_CODEPOINT_SURROGATE_END
+ 1;
1359 if (cupper
> SCM_CODEPOINT_MAX
)
1360 cupper
= SCM_CODEPOINT_MAX
;
1361 if (cupper
>= SCM_CODEPOINT_SURROGATE_START
&& cupper
<= SCM_CODEPOINT_SURROGATE_END
)
1362 cupper
= SCM_CODEPOINT_SURROGATE_START
- 1;
1363 if (clower
< SCM_CODEPOINT_SURROGATE_START
&& cupper
> SCM_CODEPOINT_SURROGATE_END
)
1365 scm_i_charset_set_range (SCM_CHARSET_DATA (cs
), clower
, SCM_CODEPOINT_SURROGATE_START
- 1);
1366 scm_i_charset_set_range (SCM_CHARSET_DATA (cs
), SCM_CODEPOINT_SURROGATE_END
+ 1, cupper
);
1369 scm_i_charset_set_range (SCM_CHARSET_DATA (cs
), clower
, cupper
);
1373 SCM_DEFINE (scm_ucs_range_to_char_set
, "ucs-range->char-set", 2, 2, 0,
1374 (SCM lower
, SCM upper
, SCM error
, SCM base_cs
),
1375 "Return a character set containing all characters whose\n"
1376 "character codes lie in the half-open range\n"
1377 "[@var{lower},@var{upper}).\n"
1379 "If @var{error} is a true value, an error is signalled if the\n"
1380 "specified range contains characters which are not valid\n"
1381 "Unicode code points. If @var{error} is @code{#f},\n"
1382 "these characters are silently left out of the resultung\n"
1385 "The characters in @var{base_cs} are added to the result, if\n"
1387 #define FUNC_NAME s_scm_ucs_range_to_char_set
1389 return scm_i_ucs_range_to_char_set (FUNC_NAME
, lower
, upper
,
1395 SCM_DEFINE (scm_ucs_range_to_char_set_x
, "ucs-range->char-set!", 4, 0, 0,
1396 (SCM lower
, SCM upper
, SCM error
, SCM base_cs
),
1397 "Return a character set containing all characters whose\n"
1398 "character codes lie in the half-open range\n"
1399 "[@var{lower},@var{upper}).\n"
1401 "If @var{error} is a true value, an error is signalled if the\n"
1402 "specified range contains characters which are not contained in\n"
1403 "the implemented character range. If @var{error} is @code{#f},\n"
1404 "these characters are silently left out of the resultung\n"
1407 "The characters are added to @var{base_cs} and @var{base_cs} is\n"
1409 #define FUNC_NAME s_scm_ucs_range_to_char_set_x
1411 SCM_VALIDATE_SMOB (4, base_cs
, charset
);
1412 return scm_i_ucs_range_to_char_set (FUNC_NAME
, lower
, upper
,
1417 SCM_DEFINE (scm_to_char_set
, "->char-set", 1, 0, 0,
1419 "Coerces x into a char-set. @var{x} may be a string, character or char-set. A string is converted to the set of its constituent characters; a character is converted to a singleton set; a char-set is returned as-is.")
1420 #define FUNC_NAME s_scm_to_char_set
1422 if (scm_is_string (x
))
1423 return scm_string_to_char_set (x
, SCM_UNDEFINED
);
1424 else if (SCM_CHARP (x
))
1425 return scm_char_set (scm_list_1 (x
));
1426 else if (SCM_SMOB_PREDICATE (scm_tc16_charset
, x
))
1429 scm_wrong_type_arg (NULL
, 0, x
);
1433 SCM_DEFINE (scm_char_set_size
, "char-set-size", 1, 0, 0,
1435 "Return the number of elements in character set @var{cs}.")
1436 #define FUNC_NAME s_scm_char_set_size
1439 scm_t_char_set
*cs_data
;
1441 SCM_VALIDATE_SMOB (1, cs
, charset
);
1442 cs_data
= SCM_CHARSET_DATA (cs
);
1444 if (cs_data
->len
== 0)
1445 return scm_from_int (0);
1447 for (k
= 0; k
< cs_data
->len
; k
++)
1448 count
+= cs_data
->ranges
[k
].hi
- cs_data
->ranges
[k
].lo
+ 1;
1450 return scm_from_int (count
);
1455 SCM_DEFINE (scm_char_set_count
, "char-set-count", 2, 0, 0,
1457 "Return the number of the elements int the character set\n"
1458 "@var{cs} which satisfy the predicate @var{pred}.")
1459 #define FUNC_NAME s_scm_char_set_count
1463 scm_t_char_set
*cs_data
;
1465 SCM_VALIDATE_PROC (1, pred
);
1466 SCM_VALIDATE_SMOB (2, cs
, charset
);
1467 cs_data
= SCM_CHARSET_DATA (cs
);
1468 if (cs_data
->len
== 0)
1469 return scm_from_int (0);
1471 for (k
= 0; k
< cs_data
->len
; k
++)
1472 for (n
= cs_data
->ranges
[k
].lo
; n
<= cs_data
->ranges
[k
].hi
; n
++)
1474 SCM res
= scm_call_1 (pred
, SCM_MAKE_CHAR (n
));
1475 if (scm_is_true (res
))
1478 return SCM_I_MAKINUM (count
);
1483 SCM_DEFINE (scm_char_set_to_list
, "char-set->list", 1, 0, 0,
1485 "Return a list containing the elements of the character set\n"
1487 #define FUNC_NAME s_scm_char_set_to_list
1491 SCM result
= SCM_EOL
;
1494 SCM_VALIDATE_SMOB (1, cs
, charset
);
1495 p
= SCM_CHARSET_DATA (cs
);
1499 for (k
= p
->len
- 1; k
>= 0; k
--)
1500 for (n
= p
->ranges
[k
].hi
; n
>= p
->ranges
[k
].lo
; n
--)
1501 result
= scm_cons (SCM_MAKE_CHAR (n
), result
);
1507 SCM_DEFINE (scm_char_set_to_string
, "char-set->string", 1, 0, 0,
1509 "Return a string containing the elements of the character set\n"
1510 "@var{cs}. The order in which the characters are placed in the\n"
1511 "string is not defined.")
1512 #define FUNC_NAME s_scm_char_set_to_string
1520 scm_t_char_set
*cs_data
;
1524 SCM_VALIDATE_SMOB (1, cs
, charset
);
1525 cs_data
= SCM_CHARSET_DATA (cs
);
1526 if (cs_data
->len
== 0)
1529 if (cs_data
->ranges
[cs_data
->len
- 1].hi
> 255)
1532 count
= scm_to_int (scm_char_set_size (cs
));
1534 result
= scm_i_make_wide_string (count
, &wbuf
);
1536 result
= scm_i_make_string (count
, &buf
);
1538 for (k
= 0; k
< cs_data
->len
; k
++)
1539 for (n
= cs_data
->ranges
[k
].lo
; n
<= cs_data
->ranges
[k
].hi
; n
++)
1551 SCM_DEFINE (scm_char_set_contains_p
, "char-set-contains?", 2, 0, 0,
1553 "Return @code{#t} iff the character @var{ch} is contained in the\n"
1554 "character set @var{cs}.")
1555 #define FUNC_NAME s_scm_char_set_contains_p
1557 SCM_VALIDATE_SMOB (1, cs
, charset
);
1558 SCM_VALIDATE_CHAR (2, ch
);
1559 return scm_from_bool (SCM_CHARSET_GET (cs
, SCM_CHAR (ch
)));
1564 SCM_DEFINE (scm_char_set_every
, "char-set-every", 2, 0, 0,
1566 "Return a true value if every character in the character set\n"
1567 "@var{cs} satisfies the predicate @var{pred}.")
1568 #define FUNC_NAME s_scm_char_set_every
1572 SCM res
= SCM_BOOL_T
;
1573 scm_t_char_set
*cs_data
;
1575 SCM_VALIDATE_PROC (1, pred
);
1576 SCM_VALIDATE_SMOB (2, cs
, charset
);
1578 cs_data
= SCM_CHARSET_DATA (cs
);
1579 if (cs_data
->len
== 0)
1582 for (k
= 0; k
< cs_data
->len
; k
++)
1583 for (n
= cs_data
->ranges
[k
].lo
; n
<= cs_data
->ranges
[k
].hi
; n
++)
1585 res
= scm_call_1 (pred
, SCM_MAKE_CHAR (n
));
1586 if (scm_is_false (res
))
1594 SCM_DEFINE (scm_char_set_any
, "char-set-any", 2, 0, 0,
1596 "Return a true value if any character in the character set\n"
1597 "@var{cs} satisfies the predicate @var{pred}.")
1598 #define FUNC_NAME s_scm_char_set_any
1602 scm_t_char_set
*cs_data
;
1604 SCM_VALIDATE_PROC (1, pred
);
1605 SCM_VALIDATE_SMOB (2, cs
, charset
);
1607 cs_data
= SCM_CHARSET_DATA (cs
);
1608 if (cs_data
->len
== 0)
1611 for (k
= 0; k
< cs_data
->len
; k
++)
1612 for (n
= cs_data
->ranges
[k
].lo
; n
<= cs_data
->ranges
[k
].hi
; n
++)
1614 SCM res
= scm_call_1 (pred
, SCM_MAKE_CHAR (n
));
1615 if (scm_is_true (res
))
1623 SCM_DEFINE (scm_char_set_adjoin
, "char-set-adjoin", 1, 0, 1,
1625 "Add all character arguments to the first argument, which must\n"
1626 "be a character set.")
1627 #define FUNC_NAME s_scm_char_set_adjoin
1629 SCM_VALIDATE_SMOB (1, cs
, charset
);
1630 SCM_VALIDATE_REST_ARGUMENT (rest
);
1631 cs
= scm_char_set_copy (cs
);
1633 while (!scm_is_null (rest
))
1635 SCM chr
= SCM_CAR (rest
);
1638 SCM_VALIDATE_CHAR_COPY (1, chr
, c
);
1639 rest
= SCM_CDR (rest
);
1641 SCM_CHARSET_SET (cs
, c
);
1648 SCM_DEFINE (scm_char_set_delete
, "char-set-delete", 1, 0, 1,
1650 "Delete all character arguments from the first argument, which\n"
1651 "must be a character set.")
1652 #define FUNC_NAME s_scm_char_set_delete
1654 SCM_VALIDATE_SMOB (1, cs
, charset
);
1655 SCM_VALIDATE_REST_ARGUMENT (rest
);
1656 cs
= scm_char_set_copy (cs
);
1658 while (!scm_is_null (rest
))
1660 SCM chr
= SCM_CAR (rest
);
1663 SCM_VALIDATE_CHAR_COPY (1, chr
, c
);
1664 rest
= SCM_CDR (rest
);
1666 SCM_CHARSET_UNSET (cs
, c
);
1673 SCM_DEFINE (scm_char_set_adjoin_x
, "char-set-adjoin!", 1, 0, 1,
1675 "Add all character arguments to the first argument, which must\n"
1676 "be a character set.")
1677 #define FUNC_NAME s_scm_char_set_adjoin_x
1679 SCM_VALIDATE_SMOB (1, cs
, charset
);
1680 SCM_VALIDATE_REST_ARGUMENT (rest
);
1682 while (!scm_is_null (rest
))
1684 SCM chr
= SCM_CAR (rest
);
1687 SCM_VALIDATE_CHAR_COPY (1, chr
, c
);
1688 rest
= SCM_CDR (rest
);
1690 SCM_CHARSET_SET (cs
, c
);
1697 SCM_DEFINE (scm_char_set_delete_x
, "char-set-delete!", 1, 0, 1,
1699 "Delete all character arguments from the first argument, which\n"
1700 "must be a character set.")
1701 #define FUNC_NAME s_scm_char_set_delete_x
1703 SCM_VALIDATE_SMOB (1, cs
, charset
);
1704 SCM_VALIDATE_REST_ARGUMENT (rest
);
1706 while (!scm_is_null (rest
))
1708 SCM chr
= SCM_CAR (rest
);
1711 SCM_VALIDATE_CHAR_COPY (1, chr
, c
);
1712 rest
= SCM_CDR (rest
);
1714 SCM_CHARSET_UNSET (cs
, c
);
1721 SCM_DEFINE (scm_char_set_complement
, "char-set-complement", 1, 0, 0,
1722 (SCM cs
), "Return the complement of the character set @var{cs}.")
1723 #define FUNC_NAME s_scm_char_set_complement
1726 scm_t_char_set
*p
, *q
;
1728 SCM_VALIDATE_SMOB (1, cs
, charset
);
1730 res
= make_char_set (FUNC_NAME
);
1731 p
= SCM_CHARSET_DATA (res
);
1732 q
= SCM_CHARSET_DATA (cs
);
1734 charsets_complement (p
, q
);
1740 SCM_DEFINE (scm_char_set_union
, "char-set-union", 0, 0, 1,
1742 "Return the union of all argument character sets.")
1743 #define FUNC_NAME s_scm_char_set_union
1749 SCM_VALIDATE_REST_ARGUMENT (rest
);
1751 res
= make_char_set (FUNC_NAME
);
1752 p
= SCM_CHARSET_DATA (res
);
1753 while (!scm_is_null (rest
))
1755 SCM cs
= SCM_CAR (rest
);
1756 SCM_VALIDATE_SMOB (c
, cs
, charset
);
1758 rest
= SCM_CDR (rest
);
1761 charsets_union (p
, (scm_t_char_set
*) SCM_SMOB_DATA (cs
));
1768 SCM_DEFINE (scm_char_set_intersection
, "char-set-intersection", 0, 0, 1,
1770 "Return the intersection of all argument character sets.")
1771 #define FUNC_NAME s_scm_char_set_intersection
1775 SCM_VALIDATE_REST_ARGUMENT (rest
);
1777 if (scm_is_null (rest
))
1778 res
= make_char_set (FUNC_NAME
);
1784 res
= scm_char_set_copy (SCM_CAR (rest
));
1785 p
= SCM_CHARSET_DATA (res
);
1786 rest
= SCM_CDR (rest
);
1788 while (scm_is_pair (rest
))
1790 SCM cs
= SCM_CAR (rest
);
1791 scm_t_char_set
*cs_data
;
1793 SCM_VALIDATE_SMOB (argnum
, cs
, charset
);
1795 cs_data
= SCM_CHARSET_DATA (cs
);
1796 rest
= SCM_CDR (rest
);
1797 charsets_intersection (p
, cs_data
);
1806 SCM_DEFINE (scm_char_set_difference
, "char-set-difference", 1, 0, 1,
1807 (SCM cs1
, SCM rest
),
1808 "Return the difference of all argument character sets.")
1809 #define FUNC_NAME s_scm_char_set_difference
1813 scm_t_char_set
*p
, *q
;
1815 SCM_VALIDATE_SMOB (1, cs1
, charset
);
1816 SCM_VALIDATE_REST_ARGUMENT (rest
);
1818 res
= scm_char_set_copy (cs1
);
1819 p
= SCM_CHARSET_DATA (res
);
1820 compl = make_char_set (FUNC_NAME
);
1821 q
= SCM_CHARSET_DATA (compl);
1822 while (!scm_is_null (rest
))
1824 SCM cs
= SCM_CAR (rest
);
1825 SCM_VALIDATE_SMOB (c
, cs
, charset
);
1827 rest
= SCM_CDR (rest
);
1829 charsets_complement (q
, SCM_CHARSET_DATA (cs
));
1830 charsets_intersection (p
, q
);
1837 SCM_DEFINE (scm_char_set_xor
, "char-set-xor", 0, 0, 1,
1839 "Return the exclusive-or of all argument character sets.")
1840 #define FUNC_NAME s_scm_char_set_xor
1844 SCM_VALIDATE_REST_ARGUMENT (rest
);
1846 if (scm_is_null (rest
))
1847 res
= make_char_set (FUNC_NAME
);
1853 res
= scm_char_set_copy (SCM_CAR (rest
));
1854 p
= SCM_CHARSET_DATA (res
);
1855 rest
= SCM_CDR (rest
);
1857 while (scm_is_pair (rest
))
1859 SCM cs
= SCM_CAR (rest
);
1860 scm_t_char_set
*cs_data
;
1862 SCM_VALIDATE_SMOB (argnum
, cs
, charset
);
1864 cs_data
= SCM_CHARSET_DATA (cs
);
1865 rest
= SCM_CDR (rest
);
1867 charsets_xor (p
, cs_data
);
1875 SCM_DEFINE (scm_char_set_diff_plus_intersection
, "char-set-diff+intersection", 1, 0, 1,
1876 (SCM cs1
, SCM rest
),
1877 "Return the difference and the intersection of all argument\n"
1879 #define FUNC_NAME s_scm_char_set_diff_plus_intersection
1883 scm_t_char_set
*p
, *q
;
1885 SCM_VALIDATE_SMOB (1, cs1
, charset
);
1886 SCM_VALIDATE_REST_ARGUMENT (rest
);
1888 res1
= scm_char_set_copy (cs1
);
1889 res2
= make_char_set (FUNC_NAME
);
1890 p
= SCM_CHARSET_DATA (res1
);
1891 q
= SCM_CHARSET_DATA (res2
);
1892 while (!scm_is_null (rest
))
1894 SCM cs
= SCM_CAR (rest
);
1897 SCM_VALIDATE_SMOB (c
, cs
, charset
);
1899 r
= SCM_CHARSET_DATA (cs
);
1901 charsets_union (q
, r
);
1902 charsets_intersection (p
, r
);
1903 rest
= SCM_CDR (rest
);
1905 return scm_values (scm_list_2 (res1
, res2
));
1910 SCM_DEFINE (scm_char_set_complement_x
, "char-set-complement!", 1, 0, 0,
1911 (SCM cs
), "Return the complement of the character set @var{cs}.")
1912 #define FUNC_NAME s_scm_char_set_complement_x
1914 SCM_VALIDATE_SMOB (1, cs
, charset
);
1915 cs
= scm_char_set_complement (cs
);
1921 SCM_DEFINE (scm_char_set_union_x
, "char-set-union!", 1, 0, 1,
1922 (SCM cs1
, SCM rest
),
1923 "Return the union of all argument character sets.")
1924 #define FUNC_NAME s_scm_char_set_union_x
1926 SCM_VALIDATE_SMOB (1, cs1
, charset
);
1927 SCM_VALIDATE_REST_ARGUMENT (rest
);
1929 cs1
= scm_char_set_union (scm_cons (cs1
, rest
));
1935 SCM_DEFINE (scm_char_set_intersection_x
, "char-set-intersection!", 1, 0, 1,
1936 (SCM cs1
, SCM rest
),
1937 "Return the intersection of all argument character sets.")
1938 #define FUNC_NAME s_scm_char_set_intersection_x
1940 SCM_VALIDATE_SMOB (1, cs1
, charset
);
1941 SCM_VALIDATE_REST_ARGUMENT (rest
);
1943 cs1
= scm_char_set_intersection (scm_cons (cs1
, rest
));
1949 SCM_DEFINE (scm_char_set_difference_x
, "char-set-difference!", 1, 0, 1,
1950 (SCM cs1
, SCM rest
),
1951 "Return the difference of all argument character sets.")
1952 #define FUNC_NAME s_scm_char_set_difference_x
1954 SCM_VALIDATE_SMOB (1, cs1
, charset
);
1955 SCM_VALIDATE_REST_ARGUMENT (rest
);
1957 cs1
= scm_char_set_difference (cs1
, rest
);
1963 SCM_DEFINE (scm_char_set_xor_x
, "char-set-xor!", 1, 0, 1,
1964 (SCM cs1
, SCM rest
),
1965 "Return the exclusive-or of all argument character sets.")
1966 #define FUNC_NAME s_scm_char_set_xor_x
1968 /* a side-effecting variant should presumably give consistent results:
1969 (define a (char-set #\a))
1970 (char-set-xor a a a) -> char set #\a
1971 (char-set-xor! a a a) -> char set #\a
1973 cs1
= scm_char_set_xor (scm_cons (cs1
, rest
));
1979 SCM_DEFINE (scm_char_set_diff_plus_intersection_x
,
1980 "char-set-diff+intersection!", 2, 0, 1, (SCM cs1
, SCM cs2
,
1982 "Return the difference and the intersection of all argument\n"
1984 #define FUNC_NAME s_scm_char_set_diff_plus_intersection_x
1986 SCM diff
, intersect
;
1988 diff
= scm_char_set_difference (cs1
, scm_cons (cs2
, rest
));
1990 scm_char_set_intersection (scm_cons (cs1
, scm_cons (cs2
, rest
)));
1993 return scm_values (scm_list_2 (cs1
, cs2
));
1999 /* Standard character sets. */
2001 SCM scm_char_set_lower_case
;
2002 SCM scm_char_set_upper_case
;
2003 SCM scm_char_set_title_case
;
2004 SCM scm_char_set_letter
;
2005 SCM scm_char_set_digit
;
2006 SCM scm_char_set_letter_and_digit
;
2007 SCM scm_char_set_graphic
;
2008 SCM scm_char_set_printing
;
2009 SCM scm_char_set_whitespace
;
2010 SCM scm_char_set_iso_control
;
2011 SCM scm_char_set_punctuation
;
2012 SCM scm_char_set_symbol
;
2013 SCM scm_char_set_hex_digit
;
2014 SCM scm_char_set_blank
;
2015 SCM scm_char_set_ascii
;
2016 SCM scm_char_set_empty
;
2017 SCM scm_char_set_full
;
2020 /* Create an empty character set and return it after binding it to NAME. */
2022 define_charset (const char *name
, const scm_t_char_set
*p
)
2026 SCM_NEWSMOB (cs
, scm_tc16_charset
, p
);
2027 scm_c_define (name
, cs
);
2028 return scm_permanent_object (cs
);
2031 #ifdef SCM_CHARSET_DEBUG
2032 SCM_DEFINE (scm_debug_char_set
, "debug-char-set", 1, 0, 0,
2034 "Print out the internal C structure of @var{charset}.\n")
2035 #define FUNC_NAME s_scm_debug_char_set
2038 scm_t_char_set
*cs
= SCM_CHARSET_DATA (charset
);
2039 fprintf (stderr
, "cs %p\n", cs
);
2040 fprintf (stderr
, "len %d\n", cs
->len
);
2041 fprintf (stderr
, "arr %p\n", cs
->ranges
);
2042 for (i
= 0; i
< cs
->len
; i
++)
2044 if (cs
->ranges
[i
].lo
== cs
->ranges
[i
].hi
)
2045 fprintf (stderr
, "%04x\n", cs
->ranges
[i
].lo
);
2047 fprintf (stderr
, "%04x..%04x\t[%d]\n",
2049 cs
->ranges
[i
].hi
, cs
->ranges
[i
].hi
- cs
->ranges
[i
].lo
+ 1);
2052 return SCM_UNSPECIFIED
;
2055 #endif /* SCM_CHARSET_DEBUG */
2060 scm_init_srfi_14 (void)
2062 scm_tc16_charset
= scm_make_smob_type ("character-set", 0);
2063 scm_set_smob_free (scm_tc16_charset
, charset_free
);
2064 scm_set_smob_print (scm_tc16_charset
, charset_print
);
2066 scm_tc16_charset_cursor
= scm_make_smob_type ("char-set-cursor", 0);
2067 scm_set_smob_free (scm_tc16_charset_cursor
, charset_cursor_free
);
2068 scm_set_smob_print (scm_tc16_charset_cursor
, charset_cursor_print
);
2070 scm_char_set_upper_case
=
2071 define_charset ("char-set:upper-case", &cs_upper_case
);
2072 scm_char_set_lower_case
=
2073 define_charset ("char-set:lower-case", &cs_lower_case
);
2074 scm_char_set_title_case
=
2075 define_charset ("char-set:title-case", &cs_title_case
);
2076 scm_char_set_letter
= define_charset ("char-set:letter", &cs_letter
);
2077 scm_char_set_digit
= define_charset ("char-set:digit", &cs_digit
);
2078 scm_char_set_letter_and_digit
=
2079 define_charset ("char-set:letter+digit", &cs_letter_plus_digit
);
2080 scm_char_set_graphic
= define_charset ("char-set:graphic", &cs_graphic
);
2081 scm_char_set_printing
= define_charset ("char-set:printing", &cs_printing
);
2082 scm_char_set_whitespace
=
2083 define_charset ("char-set:whitespace", &cs_whitespace
);
2084 scm_char_set_iso_control
=
2085 define_charset ("char-set:iso-control", &cs_iso_control
);
2086 scm_char_set_punctuation
=
2087 define_charset ("char-set:punctuation", &cs_punctuation
);
2088 scm_char_set_symbol
= define_charset ("char-set:symbol", &cs_symbol
);
2089 scm_char_set_hex_digit
=
2090 define_charset ("char-set:hex-digit", &cs_hex_digit
);
2091 scm_char_set_blank
= define_charset ("char-set:blank", &cs_blank
);
2092 scm_char_set_ascii
= define_charset ("char-set:ascii", &cs_ascii
);
2093 scm_char_set_empty
= define_charset ("char-set:empty", &cs_empty
);
2094 scm_char_set_full
= define_charset ("char-set:full", &cs_full
);
2096 #include "libguile/srfi-14.x"
2099 /* End of srfi-14.c. */