1 /* srfi-13.c --- SRFI-13 procedures for Guile
3 * Copyright (C) 2001, 2004 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
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 #include "libguile/srfi-13.h"
27 #include "libguile/srfi-14.h"
29 /* SCM_VALIDATE_SUBSTRING_SPEC_COPY is deprecated since it encourages
30 messing with the internal representation of strings. We define our
31 own version since we use it so much and are messing with Guile
35 #define MY_VALIDATE_SUBSTRING_SPEC_COPY(pos_str, str, c_str, \
36 pos_start, start, c_start, \
37 pos_end, end, c_end) \
39 SCM_VALIDATE_STRING (pos_str, str); \
40 c_str = scm_i_string_chars (str); \
41 scm_i_get_substring_spec (scm_i_string_length (str), \
42 start, &c_start, end, &c_end); \
45 #define MY_VALIDATE_SUBSTRING_SPEC(pos_str, str, \
46 pos_start, start, c_start, \
47 pos_end, end, c_end) \
49 SCM_VALIDATE_STRING (pos_str, str); \
50 scm_i_get_substring_spec (scm_i_string_length (str), \
51 start, &c_start, end, &c_end); \
54 SCM_DEFINE (scm_string_null_p
, "string-null?", 1, 0, 0,
56 "Return @code{#t} if @var{str}'s length is zero, and\n"
57 "@code{#f} otherwise.\n"
59 "(string-null? \"\") @result{} #t\n"
60 "y @result{} \"foo\"\n"
61 "(string-null? y) @result{} #f\n"
63 #define FUNC_NAME s_scm_string_null_p
65 SCM_VALIDATE_STRING (1, str
);
66 return scm_from_bool (scm_i_string_length (str
) == 0);
74 scm_misc_error (NULL
, "race condition detected", SCM_EOL
);
78 SCM_DEFINE (scm_string_any
, "string-any", 2, 2, 0,
79 (SCM char_pred
, SCM s
, SCM start
, SCM end
),
80 "Check if the predicate @var{pred} is true for any character in\n"
81 "the string @var{s}.\n"
83 "Calls to @var{pred} are made from left to right across @var{s}.\n"
84 "When it returns true (ie.@: non-@code{#f}), that return value\n"
85 "is the return from @code{string-any}.\n"
87 "The SRFI-13 specification requires that the call to @var{pred}\n"
88 "on the last character of @var{s} (assuming that point is\n"
89 "reached) be a tail call, but currently in Guile this is not the\n"
91 #define FUNC_NAME s_scm_string_any
97 MY_VALIDATE_SUBSTRING_SPEC_COPY (2, s
, cstr
,
101 if (SCM_CHARP (char_pred
))
103 res
= (memchr (cstr
+cstart
, (int) SCM_CHAR (char_pred
),
105 ? SCM_BOOL_F
: SCM_BOOL_T
);
107 else if (SCM_CHARSETP (char_pred
))
110 for (i
= cstart
; i
< cend
; i
++)
111 if (SCM_CHARSET_GET (char_pred
, cstr
[i
]))
119 SCM_VALIDATE_PROC (1, char_pred
);
121 while (cstart
< cend
)
123 res
= scm_call_1 (char_pred
, SCM_MAKE_CHAR (cstr
[cstart
]));
124 if (scm_is_true (res
))
126 cstr
= scm_i_string_chars (s
);
131 scm_remember_upto_here_1 (s
);
137 SCM_DEFINE (scm_string_every
, "string-every", 2, 2, 0,
138 (SCM char_pred
, SCM s
, SCM start
, SCM end
),
139 "Check if the predicate @var{pred} is true for every character\n"
140 "in the string @var{s}.\n"
142 "Calls to @var{pred} are made from left to right across @var{s}.\n"
143 "If the predicate is true for every character then the return\n"
144 "value from the last @var{pred} call is the return from\n"
145 "@code{string-every}.\n"
147 "If there are no characters in @var{s} (ie.@: @var{start} equals\n"
148 "@var{end}) then the return is @code{#t}.\n"
150 "The SRFI-13 specification requires that the call to @var{pred}\n"
151 "on the last character of @var{s} (assuming that point is\n"
152 "reached) be a tail call, but currently in Guile this is not the\n"
154 #define FUNC_NAME s_scm_string_every
158 SCM res
= SCM_BOOL_T
;
160 MY_VALIDATE_SUBSTRING_SPEC_COPY (2, s
, cstr
,
163 if (SCM_CHARP (char_pred
))
165 char cchr
= SCM_CHAR (char_pred
);
167 for (i
= cstart
; i
< cend
; i
++)
174 else if (SCM_CHARSETP (char_pred
))
177 for (i
= cstart
; i
< cend
; i
++)
178 if (!SCM_CHARSET_GET (char_pred
, cstr
[i
]))
186 SCM_VALIDATE_PROC (1, char_pred
);
188 while (cstart
< cend
)
190 res
= scm_call_1 (char_pred
, SCM_MAKE_CHAR (cstr
[cstart
]));
191 if (scm_is_false (res
))
193 cstr
= scm_i_string_chars (s
);
198 scm_remember_upto_here_1 (s
);
204 SCM_DEFINE (scm_string_tabulate
, "string-tabulate", 2, 0, 0,
206 "@var{proc} is an integer->char procedure. Construct a string\n"
207 "of size @var{len} by applying @var{proc} to each index to\n"
208 "produce the corresponding string element. The order in which\n"
209 "@var{proc} is applied to the indices is not specified.")
210 #define FUNC_NAME s_scm_string_tabulate
217 SCM_VALIDATE_PROC (1, proc
);
218 clen
= scm_to_size_t (len
);
219 SCM_ASSERT_RANGE (2, len
, clen
>= 0);
221 res
= scm_i_make_string (clen
, &p
);
225 /* The RES string remains untouched since nobody knows about it
226 yet. No need to refetch P.
228 ch
= scm_call_1 (proc
, scm_from_size_t (i
));
230 SCM_MISC_ERROR ("procedure ~S returned non-char", scm_list_1 (proc
));
231 *p
++ = SCM_CHAR (ch
);
239 SCM_DEFINE (scm_substring_to_list
, "string->list", 1, 2, 0,
240 (SCM str
, SCM start
, SCM end
),
241 "Convert the string @var{str} into a list of characters.")
242 #define FUNC_NAME s_scm_substring_to_list
246 SCM result
= SCM_EOL
;
248 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, str
, cstr
,
251 while (cstart
< cend
)
254 result
= scm_cons (SCM_MAKE_CHAR (cstr
[cend
]), result
);
255 cstr
= scm_i_string_chars (str
);
257 scm_remember_upto_here_1 (str
);
262 /* We export scm_substring_to_list as "string->list" since it is
263 compatible and more general. This function remains for the benefit
264 of C code that used it.
268 scm_string_to_list (SCM str
)
270 return scm_substring_to_list (str
, SCM_UNDEFINED
, SCM_UNDEFINED
);
273 SCM_DEFINE (scm_reverse_list_to_string
, "reverse-list->string", 1, 0, 0,
275 "An efficient implementation of @code{(compose string->list\n"
279 "(reverse-list->string '(#\\a #\\B #\\c)) @result{} \"cBa\"\n"
281 #define FUNC_NAME s_scm_reverse_list_to_string
284 long i
= scm_ilength (chrs
);
288 SCM_WRONG_TYPE_ARG (1, chrs
);
289 result
= scm_i_make_string (i
, &data
);
294 while (i
> 0 && SCM_CONSP (chrs
))
296 SCM elt
= SCM_CAR (chrs
);
298 SCM_VALIDATE_CHAR (SCM_ARGn
, elt
);
300 *data
= SCM_CHAR (elt
);
301 chrs
= SCM_CDR (chrs
);
311 SCM_SYMBOL (scm_sym_infix
, "infix");
312 SCM_SYMBOL (scm_sym_strict_infix
, "strict-infix");
313 SCM_SYMBOL (scm_sym_suffix
, "suffix");
314 SCM_SYMBOL (scm_sym_prefix
, "prefix");
317 append_string (char **sp
, size_t *lp
, SCM str
)
320 len
= scm_c_string_length (str
);
323 memcpy (*sp
, scm_i_string_chars (str
), len
);
328 SCM_DEFINE (scm_string_join
, "string-join", 1, 2, 0,
329 (SCM ls
, SCM delimiter
, SCM grammar
),
330 "Append the string in the string list @var{ls}, using the string\n"
331 "@var{delim} as a delimiter between the elements of @var{ls}.\n"
332 "@var{grammar} is a symbol which specifies how the delimiter is\n"
333 "placed between the strings, and defaults to the symbol\n"
338 "Insert the separator between list elements. An empty string\n"
339 "will produce an empty list.\n"
340 "@item string-infix\n"
341 "Like @code{infix}, but will raise an error if given the empty\n"
344 "Insert the separator after every list element.\n"
346 "Insert the separator before each list element.\n"
348 #define FUNC_NAME s_scm_string_join
351 #define GRAM_STRICT_INFIX 1
352 #define GRAM_SUFFIX 2
353 #define GRAM_PREFIX 3
356 int gram
= GRAM_INFIX
;
360 long strings
= scm_ilength (ls
);
362 /* Validate the string list. */
364 SCM_WRONG_TYPE_ARG (1, ls
);
366 /* Validate the delimiter and record its length. */
367 if (SCM_UNBNDP (delimiter
))
369 delimiter
= scm_from_locale_string (" ");
373 del_len
= scm_c_string_length (delimiter
);
375 /* Validate the grammar symbol and remember the grammar. */
376 if (SCM_UNBNDP (grammar
))
378 else if (scm_is_eq (grammar
, scm_sym_infix
))
380 else if (scm_is_eq (grammar
, scm_sym_strict_infix
))
381 gram
= GRAM_STRICT_INFIX
;
382 else if (scm_is_eq (grammar
, scm_sym_suffix
))
384 else if (scm_is_eq (grammar
, scm_sym_prefix
))
387 SCM_WRONG_TYPE_ARG (3, grammar
);
389 /* Check grammar constraints and calculate the space required for
395 len
= (strings
> 0) ? ((strings
- 1) * del_len
) : 0;
397 case GRAM_STRICT_INFIX
:
399 SCM_MISC_ERROR ("strict-infix grammar requires non-empty list",
401 len
= (strings
- 1) * del_len
;
404 len
= strings
* del_len
;
409 while (SCM_CONSP (tmp
))
411 len
+= scm_c_string_length (SCM_CAR (tmp
));
415 result
= scm_i_make_string (len
, &p
);
421 case GRAM_STRICT_INFIX
:
422 while (SCM_CONSP (tmp
))
424 append_string (&p
, &len
, SCM_CAR (tmp
));
425 if (!SCM_NULLP (SCM_CDR (tmp
)) && del_len
> 0)
426 append_string (&p
, &len
, delimiter
);
431 while (SCM_CONSP (tmp
))
433 append_string (&p
, &len
, SCM_CAR (tmp
));
435 append_string (&p
, &len
, delimiter
);
440 while (SCM_CONSP (tmp
))
443 append_string (&p
, &len
, delimiter
);
444 append_string (&p
, &len
, SCM_CAR (tmp
));
452 #undef GRAM_STRICT_INFIX
459 /* There are a number of functions to consider here for Scheme and C:
461 string-copy STR [start [end]] ;; SRFI-13 variant of R5RS string-copy
462 substring/copy STR start [end] ;; Guile variant of R5RS substring
464 scm_string_copy (str) ;; Old function from Guile
465 scm_substring_copy (str, [start, [end]])
466 ;; C version of SRFI-13 string-copy
467 ;; and C version of substring/copy
469 The C function underlying string-copy is not exported to C
470 programs. scm_substring_copy is defined in strings.c as the
471 underlying function of substring/copy and allows an optional START
475 SCM
scm_srfi13_substring_copy (SCM str
, SCM start
, SCM end
);
477 SCM_DEFINE (scm_srfi13_substring_copy
, "string-copy", 1, 2, 0,
478 (SCM str
, SCM start
, SCM end
),
479 "Return a freshly allocated copy of the string @var{str}. If\n"
480 "given, @var{start} and @var{end} delimit the portion of\n"
481 "@var{str} which is copied.")
482 #define FUNC_NAME s_scm_srfi13_substring_copy
487 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, str
, cstr
,
490 return scm_c_substring_copy (str
, cstart
, cend
);
495 scm_string_copy (SCM str
)
497 return scm_c_substring (str
, 0, scm_c_string_length (str
));
500 SCM_DEFINE (scm_string_copy_x
, "string-copy!", 3, 2, 0,
501 (SCM target
, SCM tstart
, SCM s
, SCM start
, SCM end
),
502 "Copy the sequence of characters from index range [@var{start},\n"
503 "@var{end}) in string @var{s} to string @var{target}, beginning\n"
504 "at index @var{tstart}. The characters are copied left-to-right\n"
505 "or right-to-left as needed -- the copy is guaranteed to work,\n"
506 "even if @var{target} and @var{s} are the same string. It is an\n"
507 "error if the copy operation runs off the end of the target\n"
509 #define FUNC_NAME s_scm_string_copy_x
513 size_t cstart
, cend
, ctstart
, dummy
, len
;
514 SCM sdummy
= SCM_UNDEFINED
;
516 MY_VALIDATE_SUBSTRING_SPEC (1, target
,
519 MY_VALIDATE_SUBSTRING_SPEC_COPY (3, s
, cstr
,
523 SCM_ASSERT_RANGE (3, s
, len
<= scm_i_string_length (target
) - ctstart
);
525 ctarget
= scm_i_string_writable_chars (target
);
526 memmove (ctarget
+ ctstart
, cstr
+ cstart
, len
);
527 scm_i_string_stop_writing ();
528 scm_remember_upto_here_1 (target
);
530 return SCM_UNSPECIFIED
;
534 SCM_DEFINE (scm_substring_move_x
, "substring-move!", 5, 0, 0,
535 (SCM str1
, SCM start1
, SCM end1
, SCM str2
, SCM start2
),
536 "Copy the substring of @var{str1} bounded by @var{start1} and @var{end1}\n"
537 "into @var{str2} beginning at position @var{start2}.\n"
538 "@var{str1} and @var{str2} can be the same string.")
539 #define FUNC_NAME s_scm_substring_move_x
541 return scm_string_copy_x (str2
, start2
, str1
, start1
, end1
);
545 SCM_DEFINE (scm_string_take
, "string-take", 2, 0, 0,
547 "Return the @var{n} first characters of @var{s}.")
548 #define FUNC_NAME s_scm_string_take
550 return scm_substring (s
, SCM_INUM0
, n
);
555 SCM_DEFINE (scm_string_drop
, "string-drop", 2, 0, 0,
557 "Return all but the first @var{n} characters of @var{s}.")
558 #define FUNC_NAME s_scm_string_drop
560 return scm_substring (s
, n
, SCM_UNDEFINED
);
565 SCM_DEFINE (scm_string_take_right
, "string-take-right", 2, 0, 0,
567 "Return the @var{n} last characters of @var{s}.")
568 #define FUNC_NAME s_scm_string_take_right
570 return scm_substring (s
,
571 scm_difference (scm_string_length (s
), n
),
577 SCM_DEFINE (scm_string_drop_right
, "string-drop-right", 2, 0, 0,
579 "Return all but the last @var{n} characters of @var{s}.")
580 #define FUNC_NAME s_scm_string_drop_right
582 return scm_substring (s
,
584 scm_difference (scm_string_length (s
), n
));
589 SCM_DEFINE (scm_string_pad
, "string-pad", 2, 3, 0,
590 (SCM s
, SCM len
, SCM chr
, SCM start
, SCM end
),
591 "Take that characters from @var{start} to @var{end} from the\n"
592 "string @var{s} and return a new string, right-padded by the\n"
593 "character @var{chr} to length @var{len}. If the resulting\n"
594 "string is longer than @var{len}, it is truncated on the right.")
595 #define FUNC_NAME s_scm_string_pad
598 size_t cstart
, cend
, clen
;
600 MY_VALIDATE_SUBSTRING_SPEC (1, s
,
603 clen
= scm_to_size_t (len
);
605 if (SCM_UNBNDP (chr
))
609 SCM_VALIDATE_CHAR (3, chr
);
610 cchr
= SCM_CHAR (chr
);
612 if (clen
< (cend
- cstart
))
613 return scm_c_substring (s
, cend
- clen
, cend
);
619 result
= scm_i_make_string (clen
, &dst
);
620 memset (dst
, cchr
, (clen
- (cend
- cstart
)));
621 memmove (dst
+ clen
- (cend
- cstart
),
622 scm_i_string_chars (s
) + cstart
, cend
- cstart
);
629 SCM_DEFINE (scm_string_pad_right
, "string-pad-right", 2, 3, 0,
630 (SCM s
, SCM len
, SCM chr
, SCM start
, SCM end
),
631 "Take that characters from @var{start} to @var{end} from the\n"
632 "string @var{s} and return a new string, left-padded by the\n"
633 "character @var{chr} to length @var{len}. If the resulting\n"
634 "string is longer than @var{len}, it is truncated on the left.")
635 #define FUNC_NAME s_scm_string_pad_right
638 size_t cstart
, cend
, clen
;
640 MY_VALIDATE_SUBSTRING_SPEC (1, s
,
643 clen
= scm_to_size_t (len
);
645 if (SCM_UNBNDP (chr
))
649 SCM_VALIDATE_CHAR (3, chr
);
650 cchr
= SCM_CHAR (chr
);
652 if (clen
< (cend
- cstart
))
653 return scm_c_substring (s
, cstart
, cstart
+ clen
);
659 result
= scm_i_make_string (clen
, &dst
);
660 memset (dst
+ (cend
- cstart
), cchr
, clen
- (cend
- cstart
));
661 memmove (dst
, scm_i_string_chars (s
) + cstart
, cend
- cstart
);
668 SCM_DEFINE (scm_string_trim
, "string-trim", 1, 3, 0,
669 (SCM s
, SCM char_pred
, SCM start
, SCM end
),
670 "Trim @var{s} by skipping over all characters on the left\n"
671 "that satisfy the parameter @var{char_pred}:\n"
675 "if it is the character @var{ch}, characters equal to\n"
676 "@var{ch} are trimmed,\n"
679 "if it is a procedure @var{pred} characters that\n"
680 "satisfy @var{pred} are trimmed,\n"
683 "if it is a character set, characters in that set are trimmed.\n"
686 "If called without a @var{char_pred} argument, all whitespace is\n"
688 #define FUNC_NAME s_scm_string_trim
693 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, s
, cstr
,
696 if (SCM_UNBNDP (char_pred
))
698 while (cstart
< cend
)
700 if (!isspace((int) (unsigned char) cstr
[cstart
]))
705 else if (SCM_CHARP (char_pred
))
707 char chr
= SCM_CHAR (char_pred
);
708 while (cstart
< cend
)
710 if (chr
!= cstr
[cstart
])
715 else if (SCM_CHARSETP (char_pred
))
717 while (cstart
< cend
)
719 if (!SCM_CHARSET_GET (char_pred
, cstr
[cstart
]))
726 SCM_VALIDATE_PROC (2, char_pred
);
727 while (cstart
< cend
)
731 res
= scm_call_1 (char_pred
, SCM_MAKE_CHAR (cstr
[cstart
]));
732 if (scm_is_false (res
))
734 cstr
= scm_i_string_chars (s
);
738 return scm_c_substring (s
, cstart
, cend
);
743 SCM_DEFINE (scm_string_trim_right
, "string-trim-right", 1, 3, 0,
744 (SCM s
, SCM char_pred
, SCM start
, SCM end
),
745 "Trim @var{s} by skipping over all characters on the rightt\n"
746 "that satisfy the parameter @var{char_pred}:\n"
750 "if it is the character @var{ch}, characters equal to @var{ch}\n"
754 "if it is a procedure @var{pred} characters that satisfy\n"
755 "@var{pred} are trimmed,\n"
758 "if it is a character sets, all characters in that set are\n"
762 "If called without a @var{char_pred} argument, all whitespace is\n"
764 #define FUNC_NAME s_scm_string_trim_right
769 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, s
, cstr
,
772 if (SCM_UNBNDP (char_pred
))
774 while (cstart
< cend
)
776 if (!isspace((int) (unsigned char) cstr
[cend
- 1]))
781 else if (SCM_CHARP (char_pred
))
783 char chr
= SCM_CHAR (char_pred
);
784 while (cstart
< cend
)
786 if (chr
!= cstr
[cend
- 1])
791 else if (SCM_CHARSETP (char_pred
))
793 while (cstart
< cend
)
795 if (!SCM_CHARSET_GET (char_pred
, cstr
[cend
- 1]))
802 SCM_VALIDATE_PROC (2, char_pred
);
803 while (cstart
< cend
)
807 res
= scm_call_1 (char_pred
, SCM_MAKE_CHAR (cstr
[cend
- 1]));
808 if (scm_is_false (res
))
810 cstr
= scm_i_string_chars (s
);
814 return scm_c_substring (s
, cstart
, cend
);
819 SCM_DEFINE (scm_string_trim_both
, "string-trim-both", 1, 3, 0,
820 (SCM s
, SCM char_pred
, SCM start
, SCM end
),
821 "Trim @var{s} by skipping over all characters on both sides of\n"
822 "the string that satisfy the parameter @var{char_pred}:\n"
826 "if it is the character @var{ch}, characters equal to @var{ch}\n"
830 "if it is a procedure @var{pred} characters that satisfy\n"
831 "@var{pred} are trimmed,\n"
834 "if it is a character set, the characters in the set are\n"
838 "If called without a @var{char_pred} argument, all whitespace is\n"
840 #define FUNC_NAME s_scm_string_trim_both
845 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, s
, cstr
,
848 if (SCM_UNBNDP (char_pred
))
850 while (cstart
< cend
)
852 if (!isspace((int) (unsigned char) cstr
[cstart
]))
856 while (cstart
< cend
)
858 if (!isspace((int) (unsigned char) cstr
[cend
- 1]))
863 else if (SCM_CHARP (char_pred
))
865 char chr
= SCM_CHAR (char_pred
);
866 while (cstart
< cend
)
868 if (chr
!= cstr
[cstart
])
872 while (cstart
< cend
)
874 if (chr
!= cstr
[cend
- 1])
879 else if (SCM_CHARSETP (char_pred
))
881 while (cstart
< cend
)
883 if (!SCM_CHARSET_GET (char_pred
, cstr
[cstart
]))
887 while (cstart
< cend
)
889 if (!SCM_CHARSET_GET (char_pred
, cstr
[cend
- 1]))
896 SCM_VALIDATE_PROC (2, char_pred
);
897 while (cstart
< cend
)
901 res
= scm_call_1 (char_pred
, SCM_MAKE_CHAR (cstr
[cstart
]));
902 if (scm_is_false (res
))
904 cstr
= scm_i_string_chars (s
);
907 while (cstart
< cend
)
911 res
= scm_call_1 (char_pred
, SCM_MAKE_CHAR (cstr
[cend
- 1]));
912 if (scm_is_false (res
))
914 cstr
= scm_i_string_chars (s
);
918 return scm_c_substring (s
, cstart
, cend
);
923 SCM_DEFINE (scm_substring_fill_x
, "string-fill!", 2, 2, 0,
924 (SCM str
, SCM chr
, SCM start
, SCM end
),
925 "Stores @var{chr} in every element of the given @var{str} and\n"
926 "returns an unspecified value.")
927 #define FUNC_NAME s_scm_substring_fill_x
934 /* Older versions of Guile provided the function
935 scm_substring_fill_x with the following order of arguments:
939 We accomodate this here by detecting such a usage and reordering
950 MY_VALIDATE_SUBSTRING_SPEC (1, str
,
953 SCM_VALIDATE_CHAR_COPY (2, chr
, c
);
955 cstr
= scm_i_string_writable_chars (str
);
956 for (k
= cstart
; k
< cend
; k
++)
958 scm_i_string_stop_writing ();
959 scm_remember_upto_here_1 (str
);
961 return SCM_UNSPECIFIED
;
966 scm_string_fill_x (SCM str
, SCM chr
)
968 return scm_substring_fill_x (str
, chr
, SCM_UNDEFINED
, SCM_UNDEFINED
);
971 SCM_DEFINE (scm_string_compare
, "string-compare", 5, 4, 0,
972 (SCM s1
, SCM s2
, SCM proc_lt
, SCM proc_eq
, SCM proc_gt
, SCM start1
, SCM end1
, SCM start2
, SCM end2
),
973 "Apply @var{proc_lt}, @var{proc_eq}, @var{proc_gt} to the\n"
974 "mismatch index, depending upon whether @var{s1} is less than,\n"
975 "equal to, or greater than @var{s2}. The mismatch index is the\n"
976 "largest index @var{i} such that for every 0 <= @var{j} <\n"
977 "@var{i}, @var{s1}[@var{j}] = @var{s2}[@var{j}] -- that is,\n"
978 "@var{i} is the first position that does not match.")
979 #define FUNC_NAME s_scm_string_compare
981 const char *cstr1
, *cstr2
;
982 size_t cstart1
, cend1
, cstart2
, cend2
;
985 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, s1
, cstr1
,
988 MY_VALIDATE_SUBSTRING_SPEC_COPY (2, s2
, cstr2
,
991 SCM_VALIDATE_PROC (3, proc_lt
);
992 SCM_VALIDATE_PROC (4, proc_eq
);
993 SCM_VALIDATE_PROC (5, proc_gt
);
995 while (cstart1
< cend1
&& cstart2
< cend2
)
997 if (cstr1
[cstart1
] < cstr2
[cstart2
])
1002 else if (cstr1
[cstart1
] > cstr2
[cstart2
])
1010 if (cstart1
< cend1
)
1012 else if (cstart2
< cend2
)
1018 scm_remember_upto_here_2 (s1
, s2
);
1019 return scm_call_1 (proc
, scm_from_size_t (cstart1
));
1024 SCM_DEFINE (scm_string_compare_ci
, "string-compare-ci", 5, 4, 0,
1025 (SCM s1
, SCM s2
, SCM proc_lt
, SCM proc_eq
, SCM proc_gt
, SCM start1
, SCM end1
, SCM start2
, SCM end2
),
1026 "Apply @var{proc_lt}, @var{proc_eq}, @var{proc_gt} to the\n"
1027 "mismatch index, depending upon whether @var{s1} is less than,\n"
1028 "equal to, or greater than @var{s2}. The mismatch index is the\n"
1029 "largest index @var{i} such that for every 0 <= @var{j} <\n"
1030 "@var{i}, @var{s1}[@var{j}] = @var{s2}[@var{j}] -- that is,\n"
1031 "@var{i} is the first position that does not match. The\n"
1032 "character comparison is done case-insensitively.")
1033 #define FUNC_NAME s_scm_string_compare_ci
1035 const char *cstr1
, *cstr2
;
1036 size_t cstart1
, cend1
, cstart2
, cend2
;
1039 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, s1
, cstr1
,
1042 MY_VALIDATE_SUBSTRING_SPEC_COPY (2, s2
, cstr2
,
1045 SCM_VALIDATE_PROC (3, proc_lt
);
1046 SCM_VALIDATE_PROC (4, proc_eq
);
1047 SCM_VALIDATE_PROC (5, proc_gt
);
1049 while (cstart1
< cend1
&& cstart2
< cend2
)
1051 if (scm_c_downcase (cstr1
[cstart1
]) < scm_c_downcase (cstr2
[cstart2
]))
1056 else if (scm_c_downcase (cstr1
[cstart1
])
1057 > scm_c_downcase (cstr2
[cstart2
]))
1066 if (cstart1
< cend1
)
1068 else if (cstart2
< cend2
)
1074 scm_remember_upto_here (s1
, s2
);
1075 return scm_call_1 (proc
, scm_from_size_t (cstart1
));
1080 SCM_DEFINE (scm_string_eq
, "string=", 2, 4, 0,
1081 (SCM s1
, SCM s2
, SCM start1
, SCM end1
, SCM start2
, SCM end2
),
1082 "Return @code{#f} if @var{s1} and @var{s2} are not equal, a true\n"
1084 #define FUNC_NAME s_scm_string_eq
1086 const char *cstr1
, *cstr2
;
1087 size_t cstart1
, cend1
, cstart2
, cend2
;
1089 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, s1
, cstr1
,
1092 MY_VALIDATE_SUBSTRING_SPEC_COPY (2, s2
, cstr2
,
1096 if ((cend1
- cstart1
) != (cend2
- cstart2
))
1099 while (cstart1
< cend1
)
1101 if (cstr1
[cstart1
] < cstr2
[cstart2
])
1103 else if (cstr1
[cstart1
] > cstr2
[cstart2
])
1109 scm_remember_upto_here_2 (s1
, s2
);
1110 return scm_from_size_t (cstart1
);
1113 scm_remember_upto_here_2 (s1
, s2
);
1119 SCM_DEFINE (scm_string_neq
, "string<>", 2, 4, 0,
1120 (SCM s1
, SCM s2
, SCM start1
, SCM end1
, SCM start2
, SCM end2
),
1121 "Return @code{#f} if @var{s1} and @var{s2} are equal, a true\n"
1123 #define FUNC_NAME s_scm_string_neq
1125 const char *cstr1
, *cstr2
;
1126 size_t cstart1
, cend1
, cstart2
, cend2
;
1128 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, s1
, cstr1
,
1131 MY_VALIDATE_SUBSTRING_SPEC_COPY (2, s2
, cstr2
,
1135 while (cstart1
< cend1
&& cstart2
< cend2
)
1137 if (cstr1
[cstart1
] < cstr2
[cstart2
])
1139 else if (cstr1
[cstart1
] > cstr2
[cstart2
])
1144 if (cstart1
< cend1
)
1146 else if (cstart2
< cend2
)
1152 scm_remember_upto_here_2 (s1
, s2
);
1153 return scm_from_size_t (cstart1
);
1156 scm_remember_upto_here_2 (s1
, s2
);
1162 SCM_DEFINE (scm_string_lt
, "string<", 2, 4, 0,
1163 (SCM s1
, SCM s2
, SCM start1
, SCM end1
, SCM start2
, SCM end2
),
1164 "Return @code{#f} if @var{s1} is greater or equal to @var{s2}, a\n"
1165 "true value otherwise.")
1166 #define FUNC_NAME s_scm_string_lt
1168 const char *cstr1
, *cstr2
;
1169 size_t cstart1
, cend1
, cstart2
, cend2
;
1171 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, s1
, cstr1
,
1174 MY_VALIDATE_SUBSTRING_SPEC_COPY (2, s2
, cstr2
,
1178 while (cstart1
< cend1
&& cstart2
< cend2
)
1180 if (cstr1
[cstart1
] < cstr2
[cstart2
])
1182 else if (cstr1
[cstart1
] > cstr2
[cstart2
])
1187 if (cstart1
< cend1
)
1189 else if (cstart2
< cend2
)
1195 scm_remember_upto_here_2 (s1
, s2
);
1196 return scm_from_size_t (cstart1
);
1199 scm_remember_upto_here_2 (s1
, s2
);
1205 SCM_DEFINE (scm_string_gt
, "string>", 2, 4, 0,
1206 (SCM s1
, SCM s2
, SCM start1
, SCM end1
, SCM start2
, SCM end2
),
1207 "Return @code{#f} if @var{s1} is less or equal to @var{s2}, a\n"
1208 "true value otherwise.")
1209 #define FUNC_NAME s_scm_string_gt
1211 const char *cstr1
, *cstr2
;
1212 size_t cstart1
, cend1
, cstart2
, cend2
;
1214 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, s1
, cstr1
,
1217 MY_VALIDATE_SUBSTRING_SPEC_COPY (2, s2
, cstr2
,
1221 while (cstart1
< cend1
&& cstart2
< cend2
)
1223 if (cstr1
[cstart1
] < cstr2
[cstart2
])
1225 else if (cstr1
[cstart1
] > cstr2
[cstart2
])
1230 if (cstart1
< cend1
)
1232 else if (cstart2
< cend2
)
1238 scm_remember_upto_here_2 (s1
, s2
);
1239 return scm_from_size_t (cstart1
);
1242 scm_remember_upto_here_2 (s1
, s2
);
1248 SCM_DEFINE (scm_string_le
, "string<=", 2, 4, 0,
1249 (SCM s1
, SCM s2
, SCM start1
, SCM end1
, SCM start2
, SCM end2
),
1250 "Return @code{#f} if @var{s1} is greater to @var{s2}, a true\n"
1252 #define FUNC_NAME s_scm_string_le
1254 const char *cstr1
, *cstr2
;
1255 size_t cstart1
, cend1
, cstart2
, cend2
;
1257 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, s1
, cstr1
,
1260 MY_VALIDATE_SUBSTRING_SPEC_COPY (2, s2
, cstr2
,
1264 while (cstart1
< cend1
&& cstart2
< cend2
)
1266 if (cstr1
[cstart1
] < cstr2
[cstart2
])
1268 else if (cstr1
[cstart1
] > cstr2
[cstart2
])
1273 if (cstart1
< cend1
)
1275 else if (cstart2
< cend2
)
1281 scm_remember_upto_here_2 (s1
, s2
);
1282 return scm_from_size_t (cstart1
);
1285 scm_remember_upto_here_2 (s1
, s2
);
1291 SCM_DEFINE (scm_string_ge
, "string>=", 2, 4, 0,
1292 (SCM s1
, SCM s2
, SCM start1
, SCM end1
, SCM start2
, SCM end2
),
1293 "Return @code{#f} if @var{s1} is less to @var{s2}, a true value\n"
1295 #define FUNC_NAME s_scm_string_ge
1297 const char *cstr1
, *cstr2
;
1298 size_t cstart1
, cend1
, cstart2
, cend2
;
1300 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, s1
, cstr1
,
1303 MY_VALIDATE_SUBSTRING_SPEC_COPY (2, s2
, cstr2
,
1307 while (cstart1
< cend1
&& cstart2
< cend2
)
1309 if (cstr1
[cstart1
] < cstr2
[cstart2
])
1311 else if (cstr1
[cstart1
] > cstr2
[cstart2
])
1316 if (cstart1
< cend1
)
1318 else if (cstart2
< cend2
)
1324 scm_remember_upto_here_2 (s1
, s2
);
1325 return scm_from_size_t (cstart1
);
1328 scm_remember_upto_here_2 (s1
, s2
);
1334 SCM_DEFINE (scm_string_ci_eq
, "string-ci=", 2, 4, 0,
1335 (SCM s1
, SCM s2
, SCM start1
, SCM end1
, SCM start2
, SCM end2
),
1336 "Return @code{#f} if @var{s1} and @var{s2} are not equal, a true\n"
1337 "value otherwise. The character comparison is done\n"
1338 "case-insensitively.")
1339 #define FUNC_NAME s_scm_string_ci_eq
1341 const char *cstr1
, *cstr2
;
1342 size_t cstart1
, cend1
, cstart2
, cend2
;
1344 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, s1
, cstr1
,
1347 MY_VALIDATE_SUBSTRING_SPEC_COPY (2, s2
, cstr2
,
1351 while (cstart1
< cend1
&& cstart2
< cend2
)
1353 if (scm_c_downcase (cstr1
[cstart1
]) < scm_c_downcase (cstr2
[cstart2
]))
1355 else if (scm_c_downcase (cstr1
[cstart1
]) > scm_c_downcase (cstr2
[cstart2
]))
1360 if (cstart1
< cend1
)
1362 else if (cstart2
< cend2
)
1368 scm_remember_upto_here_2 (s1
, s2
);
1369 return scm_from_size_t (cstart1
);
1372 scm_remember_upto_here_2 (s1
, s2
);
1378 SCM_DEFINE (scm_string_ci_neq
, "string-ci<>", 2, 4, 0,
1379 (SCM s1
, SCM s2
, SCM start1
, SCM end1
, SCM start2
, SCM end2
),
1380 "Return @code{#f} if @var{s1} and @var{s2} are equal, a true\n"
1381 "value otherwise. The character comparison is done\n"
1382 "case-insensitively.")
1383 #define FUNC_NAME s_scm_string_ci_neq
1385 const char *cstr1
, *cstr2
;
1386 size_t cstart1
, cend1
, cstart2
, cend2
;
1388 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, s1
, cstr1
,
1391 MY_VALIDATE_SUBSTRING_SPEC_COPY (2, s2
, cstr2
,
1395 while (cstart1
< cend1
&& cstart2
< cend2
)
1397 if (scm_c_downcase (cstr1
[cstart1
]) < scm_c_downcase (cstr2
[cstart2
]))
1399 else if (scm_c_downcase (cstr1
[cstart1
]) > scm_c_downcase (cstr2
[cstart2
]))
1404 if (cstart1
< cend1
)
1406 else if (cstart2
< cend2
)
1412 scm_remember_upto_here_2 (s1
, s2
);
1413 return scm_from_size_t (cstart1
);
1416 scm_remember_upto_here_2 (s1
, s2
);
1422 SCM_DEFINE (scm_string_ci_lt
, "string-ci<", 2, 4, 0,
1423 (SCM s1
, SCM s2
, SCM start1
, SCM end1
, SCM start2
, SCM end2
),
1424 "Return @code{#f} if @var{s1} is greater or equal to @var{s2}, a\n"
1425 "true value otherwise. The character comparison is done\n"
1426 "case-insensitively.")
1427 #define FUNC_NAME s_scm_string_ci_lt
1429 const char *cstr1
, *cstr2
;
1430 size_t cstart1
, cend1
, cstart2
, cend2
;
1432 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, s1
, cstr1
,
1435 MY_VALIDATE_SUBSTRING_SPEC_COPY (2, s2
, cstr2
,
1439 while (cstart1
< cend1
&& cstart2
< cend2
)
1441 if (scm_c_downcase (cstr1
[cstart1
]) < scm_c_downcase (cstr2
[cstart2
]))
1443 else if (scm_c_downcase (cstr1
[cstart1
]) > scm_c_downcase (cstr2
[cstart2
]))
1448 if (cstart1
< cend1
)
1450 else if (cstart2
< cend2
)
1456 scm_remember_upto_here_2 (s1
, s2
);
1457 return scm_from_size_t (cstart1
);
1460 scm_remember_upto_here_2 (s1
, s2
);
1466 SCM_DEFINE (scm_string_ci_gt
, "string-ci>", 2, 4, 0,
1467 (SCM s1
, SCM s2
, SCM start1
, SCM end1
, SCM start2
, SCM end2
),
1468 "Return @code{#f} if @var{s1} is less or equal to @var{s2}, a\n"
1469 "true value otherwise. The character comparison is done\n"
1470 "case-insensitively.")
1471 #define FUNC_NAME s_scm_string_ci_gt
1473 const char *cstr1
, *cstr2
;
1474 size_t cstart1
, cend1
, cstart2
, cend2
;
1476 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, s1
, cstr1
,
1479 MY_VALIDATE_SUBSTRING_SPEC_COPY (2, s2
, cstr2
,
1483 while (cstart1
< cend1
&& cstart2
< cend2
)
1485 if (scm_c_downcase (cstr1
[cstart1
]) < scm_c_downcase (cstr2
[cstart2
]))
1487 else if (scm_c_downcase (cstr1
[cstart1
]) > scm_c_downcase (cstr2
[cstart2
]))
1492 if (cstart1
< cend1
)
1494 else if (cstart2
< cend2
)
1500 scm_remember_upto_here_2 (s1
, s2
);
1501 return scm_from_size_t (cstart1
);
1504 scm_remember_upto_here_2 (s1
, s2
);
1510 SCM_DEFINE (scm_string_ci_le
, "string-ci<=", 2, 4, 0,
1511 (SCM s1
, SCM s2
, SCM start1
, SCM end1
, SCM start2
, SCM end2
),
1512 "Return @code{#f} if @var{s1} is greater to @var{s2}, a true\n"
1513 "value otherwise. The character comparison is done\n"
1514 "case-insensitively.")
1515 #define FUNC_NAME s_scm_string_ci_le
1517 const char *cstr1
, *cstr2
;
1518 size_t cstart1
, cend1
, cstart2
, cend2
;
1520 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, s1
, cstr1
,
1523 MY_VALIDATE_SUBSTRING_SPEC_COPY (2, s2
, cstr2
,
1527 while (cstart1
< cend1
&& cstart2
< cend2
)
1529 if (scm_c_downcase (cstr1
[cstart1
]) < scm_c_downcase (cstr2
[cstart2
]))
1531 else if (scm_c_downcase (cstr1
[cstart1
]) > scm_c_downcase (cstr2
[cstart2
]))
1536 if (cstart1
< cend1
)
1538 else if (cstart2
< cend2
)
1544 scm_remember_upto_here_2 (s1
, s2
);
1545 return scm_from_size_t (cstart1
);
1548 scm_remember_upto_here_2 (s1
, s2
);
1554 SCM_DEFINE (scm_string_ci_ge
, "string-ci>=", 2, 4, 0,
1555 (SCM s1
, SCM s2
, SCM start1
, SCM end1
, SCM start2
, SCM end2
),
1556 "Return @code{#f} if @var{s1} is less to @var{s2}, a true value\n"
1557 "otherwise. The character comparison is done\n"
1558 "case-insensitively.")
1559 #define FUNC_NAME s_scm_string_ci_ge
1561 const char *cstr1
, *cstr2
;
1562 size_t cstart1
, cend1
, cstart2
, cend2
;
1564 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, s1
, cstr1
,
1567 MY_VALIDATE_SUBSTRING_SPEC_COPY (2, s2
, cstr2
,
1571 while (cstart1
< cend1
&& cstart2
< cend2
)
1573 if (scm_c_downcase (cstr1
[cstart1
]) < scm_c_downcase (cstr2
[cstart2
]))
1575 else if (scm_c_downcase (cstr1
[cstart1
]) > scm_c_downcase (cstr2
[cstart2
]))
1580 if (cstart1
< cend1
)
1582 else if (cstart2
< cend2
)
1588 scm_remember_upto_here_2 (s1
, s2
);
1589 return scm_from_size_t (cstart1
);
1592 scm_remember_upto_here_2 (s1
, s2
);
1597 SCM_DEFINE (scm_substring_hash
, "string-hash", 1, 3, 0,
1598 (SCM s
, SCM bound
, SCM start
, SCM end
),
1599 "Compute a hash value for @var{S}. the optional argument "
1600 "@var{bound} is a non-negative exact "
1601 "integer specifying the range of the hash function. "
1602 "A positive value restricts the return value to the "
1604 #define FUNC_NAME s_scm_substring_hash
1606 if (SCM_UNBNDP (bound
))
1607 bound
= scm_from_intmax (SCM_MOST_POSITIVE_FIXNUM
);
1608 if (SCM_UNBNDP (start
))
1610 return scm_hash (scm_substring_shared (s
, start
, end
), bound
);
1614 SCM_DEFINE (scm_substring_hash_ci
, "string-hash-ci", 1, 3, 0,
1615 (SCM s
, SCM bound
, SCM start
, SCM end
),
1616 "Compute a hash value for @var{S}. the optional argument "
1617 "@var{bound} is a non-negative exact "
1618 "integer specifying the range of the hash function. "
1619 "A positive value restricts the return value to the "
1621 #define FUNC_NAME s_scm_substring_hash_ci
1623 return scm_substring_hash (scm_substring_downcase (s
, start
, end
),
1625 SCM_UNDEFINED
, SCM_UNDEFINED
);
1629 SCM_DEFINE (scm_string_prefix_length
, "string-prefix-length", 2, 4, 0,
1630 (SCM s1
, SCM s2
, SCM start1
, SCM end1
, SCM start2
, SCM end2
),
1631 "Return the length of the longest common prefix of the two\n"
1633 #define FUNC_NAME s_scm_string_prefix_length
1635 const char *cstr1
, *cstr2
;
1636 size_t cstart1
, cend1
, cstart2
, cend2
;
1639 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, s1
, cstr1
,
1642 MY_VALIDATE_SUBSTRING_SPEC_COPY (2, s2
, cstr2
,
1645 while (cstart1
< cend1
&& cstart2
< cend2
)
1647 if (cstr1
[cstart1
] != cstr2
[cstart2
])
1655 scm_remember_upto_here_2 (s1
, s2
);
1656 return scm_from_size_t (len
);
1661 SCM_DEFINE (scm_string_prefix_length_ci
, "string-prefix-length-ci", 2, 4, 0,
1662 (SCM s1
, SCM s2
, SCM start1
, SCM end1
, SCM start2
, SCM end2
),
1663 "Return the length of the longest common prefix of the two\n"
1664 "strings, ignoring character case.")
1665 #define FUNC_NAME s_scm_string_prefix_length_ci
1667 const char *cstr1
, *cstr2
;
1668 size_t cstart1
, cend1
, cstart2
, cend2
;
1671 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, s1
, cstr1
,
1674 MY_VALIDATE_SUBSTRING_SPEC_COPY (2, s2
, cstr2
,
1677 while (cstart1
< cend1
&& cstart2
< cend2
)
1679 if (scm_c_downcase (cstr1
[cstart1
]) != scm_c_downcase (cstr2
[cstart2
]))
1687 scm_remember_upto_here_2 (s1
, s2
);
1688 return scm_from_size_t (len
);
1693 SCM_DEFINE (scm_string_suffix_length
, "string-suffix-length", 2, 4, 0,
1694 (SCM s1
, SCM s2
, SCM start1
, SCM end1
, SCM start2
, SCM end2
),
1695 "Return the length of the longest common suffix of the two\n"
1697 #define FUNC_NAME s_scm_string_suffix_length
1699 const char *cstr1
, *cstr2
;
1700 size_t cstart1
, cend1
, cstart2
, cend2
;
1703 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, s1
, cstr1
,
1706 MY_VALIDATE_SUBSTRING_SPEC_COPY (2, s2
, cstr2
,
1709 while (cstart1
< cend1
&& cstart2
< cend2
)
1713 if (cstr1
[cend1
] != cstr2
[cend2
])
1719 scm_remember_upto_here_2 (s1
, s2
);
1720 return scm_from_size_t (len
);
1725 SCM_DEFINE (scm_string_suffix_length_ci
, "string-suffix-length-ci", 2, 4, 0,
1726 (SCM s1
, SCM s2
, SCM start1
, SCM end1
, SCM start2
, SCM end2
),
1727 "Return the length of the longest common suffix of the two\n"
1728 "strings, ignoring character case.")
1729 #define FUNC_NAME s_scm_string_suffix_length_ci
1731 const char *cstr1
, *cstr2
;
1732 size_t cstart1
, cend1
, cstart2
, cend2
;
1735 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, s1
, cstr1
,
1738 MY_VALIDATE_SUBSTRING_SPEC_COPY (2, s2
, cstr2
,
1741 while (cstart1
< cend1
&& cstart2
< cend2
)
1745 if (scm_c_downcase (cstr1
[cend1
]) != scm_c_downcase (cstr2
[cend2
]))
1751 scm_remember_upto_here_2 (s1
, s2
);
1752 return scm_from_size_t (len
);
1757 SCM_DEFINE (scm_string_prefix_p
, "string-prefix?", 2, 4, 0,
1758 (SCM s1
, SCM s2
, SCM start1
, SCM end1
, SCM start2
, SCM end2
),
1759 "Is @var{s1} a prefix of @var{s2}?")
1760 #define FUNC_NAME s_scm_string_prefix_p
1762 const char *cstr1
, *cstr2
;
1763 size_t cstart1
, cend1
, cstart2
, cend2
;
1764 size_t len
= 0, len1
;
1766 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, s1
, cstr1
,
1769 MY_VALIDATE_SUBSTRING_SPEC_COPY (2, s2
, cstr2
,
1772 len1
= cend1
- cstart1
;
1773 while (cstart1
< cend1
&& cstart2
< cend2
)
1775 if (cstr1
[cstart1
] != cstr2
[cstart2
])
1783 scm_remember_upto_here_2 (s1
, s2
);
1784 return scm_from_bool (len
== len1
);
1789 SCM_DEFINE (scm_string_prefix_ci_p
, "string-prefix-ci?", 2, 4, 0,
1790 (SCM s1
, SCM s2
, SCM start1
, SCM end1
, SCM start2
, SCM end2
),
1791 "Is @var{s1} a prefix of @var{s2}, ignoring character case?")
1792 #define FUNC_NAME s_scm_string_prefix_ci_p
1794 const char *cstr1
, *cstr2
;
1795 size_t cstart1
, cend1
, cstart2
, cend2
;
1796 size_t len
= 0, len1
;
1798 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, s1
, cstr1
,
1801 MY_VALIDATE_SUBSTRING_SPEC_COPY (2, s2
, cstr2
,
1804 len1
= cend1
- cstart1
;
1805 while (cstart1
< cend1
&& cstart2
< cend2
)
1807 if (scm_c_downcase (cstr1
[cstart1
]) != scm_c_downcase (cstr2
[cstart2
]))
1815 scm_remember_upto_here_2 (s1
, s2
);
1816 return scm_from_bool (len
== len1
);
1821 SCM_DEFINE (scm_string_suffix_p
, "string-suffix?", 2, 4, 0,
1822 (SCM s1
, SCM s2
, SCM start1
, SCM end1
, SCM start2
, SCM end2
),
1823 "Is @var{s1} a suffix of @var{s2}?")
1824 #define FUNC_NAME s_scm_string_suffix_p
1826 const char *cstr1
, *cstr2
;
1827 size_t cstart1
, cend1
, cstart2
, cend2
;
1828 size_t len
= 0, len1
;
1830 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, s1
, cstr1
,
1833 MY_VALIDATE_SUBSTRING_SPEC_COPY (2, s2
, cstr2
,
1836 len1
= cend1
- cstart1
;
1837 while (cstart1
< cend1
&& cstart2
< cend2
)
1841 if (cstr1
[cend1
] != cstr2
[cend2
])
1847 scm_remember_upto_here_2 (s1
, s2
);
1848 return scm_from_bool (len
== len1
);
1853 SCM_DEFINE (scm_string_suffix_ci_p
, "string-suffix-ci?", 2, 4, 0,
1854 (SCM s1
, SCM s2
, SCM start1
, SCM end1
, SCM start2
, SCM end2
),
1855 "Is @var{s1} a suffix of @var{s2}, ignoring character case?")
1856 #define FUNC_NAME s_scm_string_suffix_ci_p
1858 const char *cstr1
, *cstr2
;
1859 size_t cstart1
, cend1
, cstart2
, cend2
;
1860 size_t len
= 0, len1
;
1862 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, s1
, cstr1
,
1865 MY_VALIDATE_SUBSTRING_SPEC_COPY (2, s2
, cstr2
,
1868 len1
= cend1
- cstart1
;
1869 while (cstart1
< cend1
&& cstart2
< cend2
)
1873 if (scm_c_downcase (cstr1
[cend1
]) != scm_c_downcase (cstr2
[cend2
]))
1879 scm_remember_upto_here_2 (s1
, s2
);
1880 return scm_from_bool (len
== len1
);
1885 SCM_DEFINE (scm_string_index
, "string-index", 2, 2, 0,
1886 (SCM s
, SCM char_pred
, SCM start
, SCM end
),
1887 "Search through the string @var{s} from left to right, returning\n"
1888 "the index of the first occurence of a character which\n"
1890 "@itemize @bullet\n"
1892 "equals @var{char_pred}, if it is character,\n"
1895 "satisifies the predicate @var{char_pred}, if it is a procedure,\n"
1898 "is in the set @var{char_pred}, if it is a character set.\n"
1900 #define FUNC_NAME s_scm_string_index
1903 size_t cstart
, cend
;
1905 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, s
, cstr
,
1908 if (SCM_CHARP (char_pred
))
1910 char cchr
= SCM_CHAR (char_pred
);
1911 while (cstart
< cend
)
1913 if (cchr
== cstr
[cstart
])
1918 else if (SCM_CHARSETP (char_pred
))
1920 while (cstart
< cend
)
1922 if (SCM_CHARSET_GET (char_pred
, cstr
[cstart
]))
1929 SCM_VALIDATE_PROC (2, char_pred
);
1930 while (cstart
< cend
)
1933 res
= scm_call_1 (char_pred
, SCM_MAKE_CHAR (cstr
[cstart
]));
1934 if (scm_is_true (res
))
1936 cstr
= scm_i_string_chars (s
);
1941 scm_remember_upto_here_1 (s
);
1945 scm_remember_upto_here_1 (s
);
1946 return scm_from_size_t (cstart
);
1950 SCM_DEFINE (scm_string_index_right
, "string-index-right", 2, 2, 0,
1951 (SCM s
, SCM char_pred
, SCM start
, SCM end
),
1952 "Search through the string @var{s} from right to left, returning\n"
1953 "the index of the last occurence of a character which\n"
1955 "@itemize @bullet\n"
1957 "equals @var{char_pred}, if it is character,\n"
1960 "satisifies the predicate @var{char_pred}, if it is a procedure,\n"
1963 "is in the set if @var{char_pred} is a character set.\n"
1965 #define FUNC_NAME s_scm_string_index_right
1968 size_t cstart
, cend
;
1970 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, s
, cstr
,
1973 if (SCM_CHARP (char_pred
))
1975 char cchr
= SCM_CHAR (char_pred
);
1976 while (cstart
< cend
)
1979 if (cchr
== cstr
[cend
])
1983 else if (SCM_CHARSETP (char_pred
))
1985 while (cstart
< cend
)
1988 if (SCM_CHARSET_GET (char_pred
, cstr
[cend
]))
1994 SCM_VALIDATE_PROC (2, char_pred
);
1995 while (cstart
< cend
)
1999 res
= scm_call_1 (char_pred
, SCM_MAKE_CHAR (cstr
[cend
]));
2000 if (scm_is_true (res
))
2002 cstr
= scm_i_string_chars (s
);
2006 scm_remember_upto_here_1 (s
);
2010 scm_remember_upto_here_1 (s
);
2011 return scm_from_size_t (cend
);
2015 SCM_DEFINE (scm_string_rindex
, "string-rindex", 2, 2, 0,
2016 (SCM s
, SCM char_pred
, SCM start
, SCM end
),
2017 "Search through the string @var{s} from right to left, returning\n"
2018 "the index of the last occurence of a character which\n"
2020 "@itemize @bullet\n"
2022 "equals @var{char_pred}, if it is character,\n"
2025 "satisifies the predicate @var{char_pred}, if it is a procedure,\n"
2028 "is in the set if @var{char_pred} is a character set.\n"
2030 #define FUNC_NAME s_scm_string_rindex
2032 return scm_string_index_right (s
, char_pred
, start
, end
);
2036 SCM_DEFINE (scm_string_skip
, "string-skip", 2, 2, 0,
2037 (SCM s
, SCM char_pred
, SCM start
, SCM end
),
2038 "Search through the string @var{s} from left to right, returning\n"
2039 "the index of the first occurence of a character which\n"
2041 "@itemize @bullet\n"
2043 "does not equal @var{char_pred}, if it is character,\n"
2046 "does not satisify the predicate @var{char_pred}, if it is a\n"
2050 "is not in the set if @var{char_pred} is a character set.\n"
2052 #define FUNC_NAME s_scm_string_skip
2055 size_t cstart
, cend
;
2057 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, s
, cstr
,
2060 if (SCM_CHARP (char_pred
))
2062 char cchr
= SCM_CHAR (char_pred
);
2063 while (cstart
< cend
)
2065 if (cchr
!= cstr
[cstart
])
2070 else if (SCM_CHARSETP (char_pred
))
2072 while (cstart
< cend
)
2074 if (!SCM_CHARSET_GET (char_pred
, cstr
[cstart
]))
2081 SCM_VALIDATE_PROC (2, char_pred
);
2082 while (cstart
< cend
)
2085 res
= scm_call_1 (char_pred
, SCM_MAKE_CHAR (cstr
[cstart
]));
2086 if (scm_is_false (res
))
2088 cstr
= scm_i_string_chars (s
);
2093 scm_remember_upto_here_1 (s
);
2097 scm_remember_upto_here_1 (s
);
2098 return scm_from_size_t (cstart
);
2103 SCM_DEFINE (scm_string_skip_right
, "string-skip-right", 2, 2, 0,
2104 (SCM s
, SCM char_pred
, SCM start
, SCM end
),
2105 "Search through the string @var{s} from right to left, returning\n"
2106 "the index of the last occurence of a character which\n"
2108 "@itemize @bullet\n"
2110 "does not equal @var{char_pred}, if it is character,\n"
2113 "does not satisfy the predicate @var{char_pred}, if it is a\n"
2117 "is not in the set if @var{char_pred} is a character set.\n"
2119 #define FUNC_NAME s_scm_string_skip_right
2122 size_t cstart
, cend
;
2124 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, s
, cstr
,
2127 if (SCM_CHARP (char_pred
))
2129 char cchr
= SCM_CHAR (char_pred
);
2130 while (cstart
< cend
)
2133 if (cchr
!= cstr
[cend
])
2137 else if (SCM_CHARSETP (char_pred
))
2139 while (cstart
< cend
)
2142 if (!SCM_CHARSET_GET (char_pred
, cstr
[cend
]))
2148 SCM_VALIDATE_PROC (2, char_pred
);
2149 while (cstart
< cend
)
2153 res
= scm_call_1 (char_pred
, SCM_MAKE_CHAR (cstr
[cend
]));
2154 if (scm_is_false (res
))
2156 cstr
= scm_i_string_chars (s
);
2160 scm_remember_upto_here_1 (s
);
2164 scm_remember_upto_here_1 (s
);
2165 return scm_from_size_t (cend
);
2171 SCM_DEFINE (scm_string_count
, "string-count", 2, 2, 0,
2172 (SCM s
, SCM char_pred
, SCM start
, SCM end
),
2173 "Return the count of the number of characters in the string\n"
2176 "@itemize @bullet\n"
2178 "equals @var{char_pred}, if it is character,\n"
2181 "satisifies the predicate @var{char_pred}, if it is a procedure.\n"
2184 "is in the set @var{char_pred}, if it is a character set.\n"
2186 #define FUNC_NAME s_scm_string_count
2189 size_t cstart
, cend
;
2192 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, s
, cstr
,
2195 if (SCM_CHARP (char_pred
))
2197 char cchr
= SCM_CHAR (char_pred
);
2198 while (cstart
< cend
)
2200 if (cchr
== cstr
[cstart
])
2205 else if (SCM_CHARSETP (char_pred
))
2207 while (cstart
< cend
)
2209 if (SCM_CHARSET_GET (char_pred
, cstr
[cstart
]))
2216 SCM_VALIDATE_PROC (2, char_pred
);
2217 while (cstart
< cend
)
2220 res
= scm_call_1 (char_pred
, SCM_MAKE_CHAR (cstr
[cstart
]));
2221 if (scm_is_true (res
))
2223 cstr
= scm_i_string_chars (s
);
2228 scm_remember_upto_here_1 (s
);
2229 return scm_from_size_t (count
);
2234 /* FIXME::martin: This should definitely get implemented more
2235 efficiently -- maybe with Knuth-Morris-Pratt, like in the reference
2237 SCM_DEFINE (scm_string_contains
, "string-contains", 2, 4, 0,
2238 (SCM s1
, SCM s2
, SCM start1
, SCM end1
, SCM start2
, SCM end2
),
2239 "Does string @var{s1} contain string @var{s2}? Return the index\n"
2240 "in @var{s1} where @var{s2} occurs as a substring, or false.\n"
2241 "The optional start/end indices restrict the operation to the\n"
2242 "indicated substrings.")
2243 #define FUNC_NAME s_scm_string_contains
2245 const char *cs1
, * cs2
;
2246 size_t cstart1
, cend1
, cstart2
, cend2
;
2249 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, s1
, cs1
,
2252 MY_VALIDATE_SUBSTRING_SPEC_COPY (2, s2
, cs2
,
2255 len2
= cend2
- cstart2
;
2256 while (cstart1
<= cend1
- len2
&& cend1
>= len2
)
2260 while (i
< cend1
&& j
< cend2
&& cs1
[i
] == cs2
[j
])
2267 scm_remember_upto_here_2 (s1
, s2
);
2268 return scm_from_size_t (cstart1
);
2273 scm_remember_upto_here_2 (s1
, s2
);
2279 /* FIXME::martin: This should definitely get implemented more
2280 efficiently -- maybe with Knuth-Morris-Pratt, like in the reference
2282 SCM_DEFINE (scm_string_contains_ci
, "string-contains-ci", 2, 4, 0,
2283 (SCM s1
, SCM s2
, SCM start1
, SCM end1
, SCM start2
, SCM end2
),
2284 "Does string @var{s1} contain string @var{s2}? Return the index\n"
2285 "in @var{s1} where @var{s2} occurs as a substring, or false.\n"
2286 "The optional start/end indices restrict the operation to the\n"
2287 "indicated substrings. Character comparison is done\n"
2288 "case-insensitively.")
2289 #define FUNC_NAME s_scm_string_contains_ci
2291 const char *cs1
, * cs2
;
2292 size_t cstart1
, cend1
, cstart2
, cend2
;
2295 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, s1
, cs1
,
2298 MY_VALIDATE_SUBSTRING_SPEC_COPY (2, s2
, cs2
,
2301 len2
= cend2
- cstart2
;
2302 while (cstart1
<= cend1
- len2
&& cend1
>= len2
)
2306 while (i
< cend1
&& j
< cend2
&&
2307 scm_c_downcase (cs1
[i
]) == scm_c_downcase (cs2
[j
]))
2314 scm_remember_upto_here_2 (s1
, s2
);
2315 return scm_from_size_t (cstart1
);
2320 scm_remember_upto_here_2 (s1
, s2
);
2326 /* Helper function for the string uppercase conversion functions.
2327 * No argument checking is performed. */
2329 string_upcase_x (SCM v
, size_t start
, size_t end
)
2334 dst
= scm_i_string_writable_chars (v
);
2335 for (k
= start
; k
< end
; ++k
)
2336 dst
[k
] = scm_c_upcase (dst
[k
]);
2337 scm_i_string_stop_writing ();
2338 scm_remember_upto_here_1 (v
);
2343 SCM_DEFINE (scm_substring_upcase_x
, "string-upcase!", 1, 2, 0,
2344 (SCM str
, SCM start
, SCM end
),
2345 "Destructively upcase every character in @code{str}.\n"
2348 "(string-upcase! y)\n"
2349 "@result{} \"ARRDEFG\"\n"
2351 "@result{} \"ARRDEFG\"\n"
2353 #define FUNC_NAME s_scm_substring_upcase_x
2356 size_t cstart
, cend
;
2358 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, str
, cstr
,
2361 return string_upcase_x (str
, cstart
, cend
);
2366 scm_string_upcase_x (SCM str
)
2368 return scm_substring_upcase_x (str
, SCM_UNDEFINED
, SCM_UNDEFINED
);
2371 SCM_DEFINE (scm_substring_upcase
, "string-upcase", 1, 2, 0,
2372 (SCM str
, SCM start
, SCM end
),
2373 "Upcase every character in @code{str}.")
2374 #define FUNC_NAME s_scm_substring_upcase
2377 size_t cstart
, cend
;
2379 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, str
, cstr
,
2382 return string_upcase_x (scm_string_copy (str
), cstart
, cend
);
2387 scm_string_upcase (SCM str
)
2389 return scm_substring_upcase (str
, SCM_UNDEFINED
, SCM_UNDEFINED
);
2392 /* Helper function for the string lowercase conversion functions.
2393 * No argument checking is performed. */
2395 string_downcase_x (SCM v
, size_t start
, size_t end
)
2400 dst
= scm_i_string_writable_chars (v
);
2401 for (k
= start
; k
< end
; ++k
)
2402 dst
[k
] = scm_c_downcase (dst
[k
]);
2403 scm_i_string_stop_writing ();
2404 scm_remember_upto_here_1 (v
);
2409 SCM_DEFINE (scm_substring_downcase_x
, "string-downcase!", 1, 2, 0,
2410 (SCM str
, SCM start
, SCM end
),
2411 "Destructively downcase every character in @var{str}.\n"
2415 "@result{} \"ARRDEFG\"\n"
2416 "(string-downcase! y)\n"
2417 "@result{} \"arrdefg\"\n"
2419 "@result{} \"arrdefg\"\n"
2421 #define FUNC_NAME s_scm_substring_downcase_x
2424 size_t cstart
, cend
;
2426 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, str
, cstr
,
2429 return string_downcase_x (str
, cstart
, cend
);
2434 scm_string_downcase_x (SCM str
)
2436 return scm_substring_downcase_x (str
, SCM_UNDEFINED
, SCM_UNDEFINED
);
2439 SCM_DEFINE (scm_substring_downcase
, "string-downcase", 1, 2, 0,
2440 (SCM str
, SCM start
, SCM end
),
2441 "Downcase every character in @var{str}.")
2442 #define FUNC_NAME s_scm_substring_downcase
2445 size_t cstart
, cend
;
2447 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, str
, cstr
,
2450 return string_downcase_x (scm_string_copy (str
), cstart
, cend
);
2455 scm_string_downcase (SCM str
)
2457 return scm_substring_downcase (str
, SCM_UNDEFINED
, SCM_UNDEFINED
);
2460 /* Helper function for the string capitalization functions.
2461 * No argument checking is performed. */
2463 string_titlecase_x (SCM str
, size_t start
, size_t end
)
2469 sz
= scm_i_string_writable_chars (str
);
2470 for(i
= start
; i
< end
; i
++)
2472 if (scm_is_true (scm_char_alphabetic_p (SCM_MAKE_CHAR (sz
[i
]))))
2476 sz
[i
] = scm_c_upcase(sz
[i
]);
2481 sz
[i
] = scm_c_downcase(sz
[i
]);
2487 scm_i_string_stop_writing ();
2488 scm_remember_upto_here_1 (str
);
2494 SCM_DEFINE (scm_string_titlecase_x
, "string-titlecase!", 1, 2, 0,
2495 (SCM str
, SCM start
, SCM end
),
2496 "Destructively titlecase every first character in a word in\n"
2498 #define FUNC_NAME s_scm_string_titlecase_x
2501 size_t cstart
, cend
;
2503 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, str
, cstr
,
2506 return string_titlecase_x (str
, cstart
, cend
);
2511 SCM_DEFINE (scm_string_titlecase
, "string-titlecase", 1, 2, 0,
2512 (SCM str
, SCM start
, SCM end
),
2513 "Titlecase every first character in a word in @var{str}.")
2514 #define FUNC_NAME s_scm_string_titlecase
2517 size_t cstart
, cend
;
2519 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, str
, cstr
,
2522 return string_titlecase_x (scm_string_copy (str
), cstart
, cend
);
2526 SCM_DEFINE (scm_string_capitalize_x
, "string-capitalize!", 1, 0, 0,
2528 "Upcase the first character of every word in @var{str}\n"
2529 "destructively and return @var{str}.\n"
2532 "y @result{} \"hello world\"\n"
2533 "(string-capitalize! y) @result{} \"Hello World\"\n"
2534 "y @result{} \"Hello World\"\n"
2536 #define FUNC_NAME s_scm_string_capitalize_x
2538 return scm_string_titlecase_x (str
, SCM_UNDEFINED
, SCM_UNDEFINED
);
2543 SCM_DEFINE (scm_string_capitalize
, "string-capitalize", 1, 0, 0,
2545 "Return a freshly allocated string with the characters in\n"
2546 "@var{str}, where the first character of every word is\n"
2548 #define FUNC_NAME s_scm_string_capitalize
2550 return scm_string_capitalize_x (scm_string_copy (str
));
2555 /* Reverse the portion of @var{str} between str[cstart] (including)
2556 and str[cend] excluding. */
2558 string_reverse_x (char * str
, size_t cstart
, size_t cend
)
2565 while (cstart
< cend
)
2568 str
[cstart
] = str
[cend
];
2577 SCM_DEFINE (scm_string_reverse
, "string-reverse", 1, 2, 0,
2578 (SCM str
, SCM start
, SCM end
),
2579 "Reverse the string @var{str}. The optional arguments\n"
2580 "@var{start} and @var{end} delimit the region of @var{str} to\n"
2582 #define FUNC_NAME s_scm_string_reverse
2586 size_t cstart
, cend
;
2589 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, str
, cstr
,
2592 result
= scm_string_copy (str
);
2593 ctarget
= scm_i_string_writable_chars (result
);
2594 string_reverse_x (ctarget
, cstart
, cend
);
2595 scm_i_string_stop_writing ();
2596 scm_remember_upto_here_1 (str
);
2602 SCM_DEFINE (scm_string_reverse_x
, "string-reverse!", 1, 2, 0,
2603 (SCM str
, SCM start
, SCM end
),
2604 "Reverse the string @var{str} in-place. The optional arguments\n"
2605 "@var{start} and @var{end} delimit the region of @var{str} to\n"
2606 "operate on. The return value is unspecified.")
2607 #define FUNC_NAME s_scm_string_reverse_x
2610 size_t cstart
, cend
;
2612 MY_VALIDATE_SUBSTRING_SPEC (1, str
,
2616 cstr
= scm_i_string_writable_chars (str
);
2617 string_reverse_x (cstr
, cstart
, cend
);
2618 scm_i_string_stop_writing ();
2619 scm_remember_upto_here_1 (str
);
2620 return SCM_UNSPECIFIED
;
2625 SCM_DEFINE (scm_string_append_shared
, "string-append/shared", 0, 0, 1,
2627 "Like @code{string-append}, but the result may share memory\n"
2628 "with the argument strings.")
2629 #define FUNC_NAME s_scm_string_append_shared
2633 SCM_VALIDATE_REST_ARGUMENT (ls
);
2635 /* Optimize the one-argument case. */
2636 i
= scm_ilength (ls
);
2638 return SCM_CAR (ls
);
2640 return scm_string_append (ls
);
2645 SCM_DEFINE (scm_string_concatenate
, "string-concatenate", 1, 0, 0,
2647 "Append the elements of @var{ls} (which must be strings)\n"
2648 "together into a single string. Guaranteed to return a freshly\n"
2649 "allocated string.")
2650 #define FUNC_NAME s_scm_string_concatenate
2652 return scm_string_append (ls
);
2657 SCM_DEFINE (scm_string_concatenate_reverse
, "string-concatenate-reverse", 1, 2, 0,
2658 (SCM ls
, SCM final_string
, SCM end
),
2659 "Without optional arguments, this procedure is equivalent to\n"
2662 "(string-concatenate (reverse ls))\n"
2665 "If the optional argument @var{final_string} is specified, it is\n"
2666 "consed onto the beginning to @var{ls} before performing the\n"
2667 "list-reverse and string-concatenate operations. If @var{end}\n"
2668 "is given, only the characters of @var{final_string} up to index\n"
2669 "@var{end} are used.\n"
2671 "Guaranteed to return a freshly allocated string.")
2672 #define FUNC_NAME s_scm_string_concatenate_reverse
2674 if (!SCM_UNBNDP (end
))
2675 final_string
= scm_substring (final_string
, SCM_INUM0
, end
);
2677 if (!SCM_UNBNDP (final_string
))
2678 ls
= scm_cons (final_string
, ls
);
2680 return scm_string_concatenate (scm_reverse (ls
));
2685 SCM_DEFINE (scm_string_concatenate_shared
, "string-concatenate/shared", 1, 0, 0,
2687 "Like @code{string-concatenate}, but the result may share memory\n"
2688 "with the strings in the list @var{ls}.")
2689 #define FUNC_NAME s_scm_string_concatenate_shared
2691 return scm_string_append_shared (ls
);
2696 SCM_DEFINE (scm_string_concatenate_reverse_shared
, "string-concatenate-reverse/shared", 1, 2, 0,
2697 (SCM ls
, SCM final_string
, SCM end
),
2698 "Like @code{string-concatenate-reverse}, but the result may\n"
2699 "share memory with the the strings in the @var{ls} arguments.")
2700 #define FUNC_NAME s_scm_string_concatenate_reverse_shared
2702 /* Just call the non-sharing version. */
2703 return scm_string_concatenate_reverse (ls
, final_string
, end
);
2708 SCM_DEFINE (scm_string_map
, "string-map", 2, 2, 0,
2709 (SCM proc
, SCM s
, SCM start
, SCM end
),
2710 "@var{proc} is a char->char procedure, it is mapped over\n"
2711 "@var{s}. The order in which the procedure is applied to the\n"
2712 "string elements is not specified.")
2713 #define FUNC_NAME s_scm_string_map
2716 size_t cstart
, cend
;
2719 SCM_VALIDATE_PROC (1, proc
);
2720 MY_VALIDATE_SUBSTRING_SPEC (2, s
,
2723 result
= scm_i_make_string (cend
- cstart
, &p
);
2724 while (cstart
< cend
)
2726 SCM ch
= scm_call_1 (proc
, scm_c_string_ref (s
, cstart
));
2727 if (!SCM_CHARP (ch
))
2728 SCM_MISC_ERROR ("procedure ~S returned non-char", scm_list_1 (proc
));
2730 *p
++ = SCM_CHAR (ch
);
2737 SCM_DEFINE (scm_string_map_x
, "string-map!", 2, 2, 0,
2738 (SCM proc
, SCM s
, SCM start
, SCM end
),
2739 "@var{proc} is a char->char procedure, it is mapped over\n"
2740 "@var{s}. The order in which the procedure is applied to the\n"
2741 "string elements is not specified. The string @var{s} is\n"
2742 "modified in-place, the return value is not specified.")
2743 #define FUNC_NAME s_scm_string_map_x
2745 size_t cstart
, cend
;
2747 SCM_VALIDATE_PROC (1, proc
);
2748 MY_VALIDATE_SUBSTRING_SPEC (2, s
,
2751 while (cstart
< cend
)
2753 SCM ch
= scm_call_1 (proc
, scm_c_string_ref (s
, cstart
));
2754 if (!SCM_CHARP (ch
))
2755 SCM_MISC_ERROR ("procedure ~S returned non-char", scm_list_1 (proc
));
2756 scm_c_string_set_x (s
, cstart
, ch
);
2759 return SCM_UNSPECIFIED
;
2764 SCM_DEFINE (scm_string_fold
, "string-fold", 3, 2, 0,
2765 (SCM kons
, SCM knil
, SCM s
, SCM start
, SCM end
),
2766 "Fold @var{kons} over the characters of @var{s}, with @var{knil}\n"
2767 "as the terminating element, from left to right. @var{kons}\n"
2768 "must expect two arguments: The actual character and the last\n"
2769 "result of @var{kons}' application.")
2770 #define FUNC_NAME s_scm_string_fold
2773 size_t cstart
, cend
;
2776 SCM_VALIDATE_PROC (1, kons
);
2777 MY_VALIDATE_SUBSTRING_SPEC_COPY (3, s
, cstr
,
2781 while (cstart
< cend
)
2783 unsigned int c
= (unsigned char) cstr
[cstart
];
2784 result
= scm_call_2 (kons
, SCM_MAKE_CHAR (c
), result
);
2785 cstr
= scm_i_string_chars (s
);
2789 scm_remember_upto_here_1 (s
);
2795 SCM_DEFINE (scm_string_fold_right
, "string-fold-right", 3, 2, 0,
2796 (SCM kons
, SCM knil
, SCM s
, SCM start
, SCM end
),
2797 "Fold @var{kons} over the characters of @var{s}, with @var{knil}\n"
2798 "as the terminating element, from right to left. @var{kons}\n"
2799 "must expect two arguments: The actual character and the last\n"
2800 "result of @var{kons}' application.")
2801 #define FUNC_NAME s_scm_string_fold_right
2804 size_t cstart
, cend
;
2807 SCM_VALIDATE_PROC (1, kons
);
2808 MY_VALIDATE_SUBSTRING_SPEC_COPY (3, s
, cstr
,
2812 while (cstart
< cend
)
2814 unsigned int c
= (unsigned char) cstr
[cend
- 1];
2815 result
= scm_call_2 (kons
, SCM_MAKE_CHAR (c
), result
);
2816 cstr
= scm_i_string_chars (s
);
2820 scm_remember_upto_here_1 (s
);
2826 SCM_DEFINE (scm_string_unfold
, "string-unfold", 4, 2, 0,
2827 (SCM p
, SCM f
, SCM g
, SCM seed
, SCM base
, SCM make_final
),
2828 "@itemize @bullet\n"
2829 "@item @var{g} is used to generate a series of @emph{seed}\n"
2830 "values from the initial @var{seed}: @var{seed}, (@var{g}\n"
2831 "@var{seed}), (@var{g}^2 @var{seed}), (@var{g}^3 @var{seed}),\n"
2833 "@item @var{p} tells us when to stop -- when it returns true\n"
2834 "when applied to one of these seed values.\n"
2835 "@item @var{f} maps each seed value to the corresponding\n"
2836 "character in the result string. These chars are assembled\n"
2837 "into the string in a left-to-right order.\n"
2838 "@item @var{base} is the optional initial/leftmost portion\n"
2839 "of the constructed string; it default to the empty\n"
2841 "@item @var{make_final} is applied to the terminal seed\n"
2842 "value (on which @var{p} returns true) to produce\n"
2843 "the final/rightmost portion of the constructed string.\n"
2844 "It defaults to @code{(lambda (x) "")}.\n"
2846 #define FUNC_NAME s_scm_string_unfold
2850 SCM_VALIDATE_PROC (1, p
);
2851 SCM_VALIDATE_PROC (2, f
);
2852 SCM_VALIDATE_PROC (3, g
);
2853 if (!SCM_UNBNDP (base
))
2855 SCM_VALIDATE_STRING (5, base
);
2859 ans
= scm_i_make_string (0, NULL
);
2860 if (!SCM_UNBNDP (make_final
))
2861 SCM_VALIDATE_PROC (6, make_final
);
2863 res
= scm_call_1 (p
, seed
);
2864 while (scm_is_false (res
))
2868 SCM ch
= scm_call_1 (f
, seed
);
2869 if (!SCM_CHARP (ch
))
2870 SCM_MISC_ERROR ("procedure ~S returned non-char", scm_list_1 (f
));
2871 str
= scm_i_make_string (1, &ptr
);
2872 *ptr
= SCM_CHAR (ch
);
2874 ans
= scm_string_append (scm_list_2 (ans
, str
));
2875 seed
= scm_call_1 (g
, seed
);
2876 res
= scm_call_1 (p
, seed
);
2878 if (!SCM_UNBNDP (make_final
))
2880 res
= scm_call_1 (make_final
, seed
);
2881 return scm_string_append (scm_list_2 (ans
, res
));
2889 SCM_DEFINE (scm_string_unfold_right
, "string-unfold-right", 4, 2, 0,
2890 (SCM p
, SCM f
, SCM g
, SCM seed
, SCM base
, SCM make_final
),
2891 "@itemize @bullet\n"
2892 "@item @var{g} is used to generate a series of @emph{seed}\n"
2893 "values from the initial @var{seed}: @var{seed}, (@var{g}\n"
2894 "@var{seed}), (@var{g}^2 @var{seed}), (@var{g}^3 @var{seed}),\n"
2896 "@item @var{p} tells us when to stop -- when it returns true\n"
2897 "when applied to one of these seed values.\n"
2898 "@item @var{f} maps each seed value to the corresponding\n"
2899 "character in the result string. These chars are assembled\n"
2900 "into the string in a right-to-left order.\n"
2901 "@item @var{base} is the optional initial/rightmost portion\n"
2902 "of the constructed string; it default to the empty\n"
2904 "@item @var{make_final} is applied to the terminal seed\n"
2905 "value (on which @var{p} returns true) to produce\n"
2906 "the final/leftmost portion of the constructed string.\n"
2907 "It defaults to @code{(lambda (x) "")}.\n"
2909 #define FUNC_NAME s_scm_string_unfold_right
2913 SCM_VALIDATE_PROC (1, p
);
2914 SCM_VALIDATE_PROC (2, f
);
2915 SCM_VALIDATE_PROC (3, g
);
2916 if (!SCM_UNBNDP (base
))
2918 SCM_VALIDATE_STRING (5, base
);
2922 ans
= scm_i_make_string (0, NULL
);
2923 if (!SCM_UNBNDP (make_final
))
2924 SCM_VALIDATE_PROC (6, make_final
);
2926 res
= scm_call_1 (p
, seed
);
2927 while (scm_is_false (res
))
2931 SCM ch
= scm_call_1 (f
, seed
);
2932 if (!SCM_CHARP (ch
))
2933 SCM_MISC_ERROR ("procedure ~S returned non-char", scm_list_1 (f
));
2934 str
= scm_i_make_string (1, &ptr
);
2935 *ptr
= SCM_CHAR (ch
);
2937 ans
= scm_string_append (scm_list_2 (str
, ans
));
2938 seed
= scm_call_1 (g
, seed
);
2939 res
= scm_call_1 (p
, seed
);
2941 if (!SCM_UNBNDP (make_final
))
2943 res
= scm_call_1 (make_final
, seed
);
2944 return scm_string_append (scm_list_2 (res
, ans
));
2952 SCM_DEFINE (scm_string_for_each
, "string-for-each", 2, 2, 0,
2953 (SCM proc
, SCM s
, SCM start
, SCM end
),
2954 "@var{proc} is mapped over @var{s} in left-to-right order. The\n"
2955 "return value is not specified.")
2956 #define FUNC_NAME s_scm_string_for_each
2959 size_t cstart
, cend
;
2961 SCM_VALIDATE_PROC (1, proc
);
2962 MY_VALIDATE_SUBSTRING_SPEC_COPY (2, s
, cstr
,
2965 while (cstart
< cend
)
2967 unsigned int c
= (unsigned char) cstr
[cstart
];
2968 scm_call_1 (proc
, SCM_MAKE_CHAR (c
));
2969 cstr
= scm_i_string_chars (s
);
2973 scm_remember_upto_here_1 (s
);
2974 return SCM_UNSPECIFIED
;
2978 SCM_DEFINE (scm_string_for_each_index
, "string-for-each-index", 2, 2, 0,
2979 (SCM proc
, SCM s
, SCM start
, SCM end
),
2980 "@var{proc} is mapped over @var{s} in left-to-right order. The\n"
2981 "return value is not specified.")
2982 #define FUNC_NAME s_scm_string_for_each_index
2984 size_t cstart
, cend
;
2986 SCM_VALIDATE_PROC (1, proc
);
2987 MY_VALIDATE_SUBSTRING_SPEC (2, s
,
2991 while (cstart
< cend
)
2993 scm_call_1 (proc
, scm_from_size_t (cstart
));
2997 scm_remember_upto_here_1 (s
);
2998 return SCM_UNSPECIFIED
;
3002 SCM_DEFINE (scm_xsubstring
, "xsubstring", 2, 3, 0,
3003 (SCM s
, SCM from
, SCM to
, SCM start
, SCM end
),
3004 "This is the @emph{extended substring} procedure that implements\n"
3005 "replicated copying of a substring of some string.\n"
3007 "@var{s} is a string, @var{start} and @var{end} are optional\n"
3008 "arguments that demarcate a substring of @var{s}, defaulting to\n"
3009 "0 and the length of @var{s}. Replicate this substring up and\n"
3010 "down index space, in both the positive and negative directions.\n"
3011 "@code{xsubstring} returns the substring of this string\n"
3012 "beginning at index @var{from}, and ending at @var{to}, which\n"
3013 "defaults to @var{from} + (@var{end} - @var{start}).")
3014 #define FUNC_NAME s_scm_xsubstring
3018 size_t cstart
, cend
;
3022 MY_VALIDATE_SUBSTRING_SPEC (1, s
,
3026 cfrom
= scm_to_int (from
);
3027 if (SCM_UNBNDP (to
))
3028 cto
= cfrom
+ (cend
- cstart
);
3030 cto
= scm_to_int (to
);
3031 if (cstart
== cend
&& cfrom
!= cto
)
3032 SCM_MISC_ERROR ("start and end indices must not be equal", SCM_EOL
);
3034 result
= scm_i_make_string (cto
- cfrom
, &p
);
3036 cs
= scm_i_string_chars (s
);
3039 size_t t
= ((cfrom
< 0) ? -cfrom
: cfrom
) % (cend
- cstart
);
3041 *p
= cs
[(cend
- cstart
) - t
];
3048 scm_remember_upto_here_1 (s
);
3054 SCM_DEFINE (scm_string_xcopy_x
, "string-xcopy!", 4, 3, 0,
3055 (SCM target
, SCM tstart
, SCM s
, SCM sfrom
, SCM sto
, SCM start
, SCM end
),
3056 "Exactly the same as @code{xsubstring}, but the extracted text\n"
3057 "is written into the string @var{target} starting at index\n"
3058 "@var{tstart}. The operation is not defined if @code{(eq?\n"
3059 "@var{target} @var{s})} or these arguments share storage -- you\n"
3060 "cannot copy a string on top of itself.")
3061 #define FUNC_NAME s_scm_string_xcopy_x
3065 size_t ctstart
, cstart
, cend
;
3067 SCM dummy
= SCM_UNDEFINED
;
3070 MY_VALIDATE_SUBSTRING_SPEC (1, target
,
3073 MY_VALIDATE_SUBSTRING_SPEC (3, s
,
3076 csfrom
= scm_to_int (sfrom
);
3077 if (SCM_UNBNDP (sto
))
3078 csto
= csfrom
+ (cend
- cstart
);
3080 csto
= scm_to_int (sto
);
3081 if (cstart
== cend
&& csfrom
!= csto
)
3082 SCM_MISC_ERROR ("start and end indices must not be equal", SCM_EOL
);
3083 SCM_ASSERT_RANGE (1, tstart
,
3084 ctstart
+ (csto
- csfrom
) <= scm_i_string_length (target
));
3086 p
= scm_i_string_writable_chars (target
) + ctstart
;
3087 cs
= scm_i_string_chars (s
);
3088 while (csfrom
< csto
)
3090 size_t t
= ((csfrom
< 0) ? -csfrom
: csfrom
) % (cend
- cstart
);
3092 *p
= cs
[(cend
- cstart
) - t
];
3098 scm_i_string_stop_writing ();
3100 scm_remember_upto_here_2 (target
, s
);
3101 return SCM_UNSPECIFIED
;
3106 SCM_DEFINE (scm_string_replace
, "string-replace", 2, 4, 0,
3107 (SCM s1
, SCM s2
, SCM start1
, SCM end1
, SCM start2
, SCM end2
),
3108 "Return the string @var{s1}, but with the characters\n"
3109 "@var{start1} @dots{} @var{end1} replaced by the characters\n"
3110 "@var{start2} @dots{} @var{end2} from @var{s2}.")
3111 #define FUNC_NAME s_scm_string_replace
3113 const char *cstr1
, *cstr2
;
3115 size_t cstart1
, cend1
, cstart2
, cend2
;
3118 MY_VALIDATE_SUBSTRING_SPEC (1, s1
,
3121 MY_VALIDATE_SUBSTRING_SPEC (2, s2
,
3124 result
= scm_i_make_string (cstart1
+ (cend2
- cstart2
) +
3125 scm_i_string_length (s1
) - cend1
, &p
);
3126 cstr1
= scm_i_string_chars (s1
);
3127 cstr2
= scm_i_string_chars (s2
);
3128 memmove (p
, cstr1
, cstart1
* sizeof (char));
3129 memmove (p
+ cstart1
, cstr2
+ cstart2
, (cend2
- cstart2
) * sizeof (char));
3130 memmove (p
+ cstart1
+ (cend2
- cstart2
),
3132 (scm_i_string_length (s1
) - cend1
) * sizeof (char));
3133 scm_remember_upto_here_2 (s1
, s2
);
3139 SCM_DEFINE (scm_string_tokenize
, "string-tokenize", 1, 3, 0,
3140 (SCM s
, SCM token_set
, SCM start
, SCM end
),
3141 "Split the string @var{s} into a list of substrings, where each\n"
3142 "substring is a maximal non-empty contiguous sequence of\n"
3143 "characters from the character set @var{token_set}, which\n"
3144 "defaults to @code{char-set:graphic}.\n"
3145 "If @var{start} or @var{end} indices are provided, they restrict\n"
3146 "@code{string-tokenize} to operating on the indicated substring\n"
3148 #define FUNC_NAME s_scm_string_tokenize
3151 size_t cstart
, cend
;
3152 SCM result
= SCM_EOL
;
3154 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, s
, cstr
,
3158 if (SCM_UNBNDP (token_set
))
3159 token_set
= scm_char_set_graphic
;
3161 if (SCM_CHARSETP (token_set
))
3165 while (cstart
< cend
)
3167 while (cstart
< cend
)
3169 if (SCM_CHARSET_GET (token_set
, cstr
[cend
- 1]))
3176 while (cstart
< cend
)
3178 if (!SCM_CHARSET_GET (token_set
, cstr
[cend
- 1]))
3182 result
= scm_cons (scm_c_substring (s
, cend
, idx
), result
);
3183 cstr
= scm_i_string_chars (s
);
3187 SCM_WRONG_TYPE_ARG (2, token_set
);
3189 scm_remember_upto_here_1 (s
);
3194 SCM_DEFINE (scm_string_split
, "string-split", 2, 0, 0,
3196 "Split the string @var{str} into the a list of the substrings delimited\n"
3197 "by appearances of the character @var{chr}. Note that an empty substring\n"
3198 "between separator characters will result in an empty string in the\n"
3202 "(string-split \"root:x:0:0:root:/root:/bin/bash\" #\\:)\n"
3204 "(\"root\" \"x\" \"0\" \"0\" \"root\" \"/root\" \"/bin/bash\")\n"
3206 "(string-split \"::\" #\\:)\n"
3208 "(\"\" \"\" \"\")\n"
3210 "(string-split \"\" #\\:)\n"
3214 #define FUNC_NAME s_scm_string_split
3221 SCM_VALIDATE_STRING (1, str
);
3222 SCM_VALIDATE_CHAR (2, chr
);
3224 idx
= scm_i_string_length (str
);
3225 p
= scm_i_string_chars (str
);
3226 ch
= SCM_CHAR (chr
);
3230 while (idx
> 0 && p
[idx
- 1] != ch
)
3234 res
= scm_cons (scm_c_substring (str
, idx
, last_idx
), res
);
3235 p
= scm_i_string_chars (str
);
3239 scm_remember_upto_here_1 (str
);
3245 SCM_DEFINE (scm_string_filter
, "string-filter", 2, 2, 0,
3246 (SCM s
, SCM char_pred
, SCM start
, SCM end
),
3247 "Filter the string @var{s}, retaining only those characters that\n"
3248 "satisfy the @var{char_pred} argument. If the argument is a\n"
3249 "procedure, it is applied to each character as a predicate, if\n"
3250 "it is a character, it is tested for equality and if it is a\n"
3251 "character set, it is tested for membership.")
3252 #define FUNC_NAME s_scm_string_filter
3255 size_t cstart
, cend
;
3259 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, s
, cstr
,
3262 if (SCM_CHARP (char_pred
))
3267 chr
= SCM_CHAR (char_pred
);
3271 if (cstr
[idx
] == chr
)
3272 ls
= scm_cons (SCM_MAKE_CHAR (cstr
[idx
]), ls
);
3273 cstr
= scm_i_string_chars (s
);
3276 result
= scm_reverse_list_to_string (ls
);
3278 else if (SCM_CHARSETP (char_pred
))
3285 if (SCM_CHARSET_GET (char_pred
, cstr
[idx
]))
3286 ls
= scm_cons (SCM_MAKE_CHAR (cstr
[idx
]), ls
);
3287 cstr
= scm_i_string_chars (s
);
3290 result
= scm_reverse_list_to_string (ls
);
3296 SCM_VALIDATE_PROC (2, char_pred
);
3301 ch
= SCM_MAKE_CHAR (cstr
[idx
]);
3302 res
= scm_call_1 (char_pred
, ch
);
3303 if (scm_is_true (res
))
3304 ls
= scm_cons (ch
, ls
);
3305 cstr
= scm_i_string_chars (s
);
3308 result
= scm_reverse_list_to_string (ls
);
3311 scm_remember_upto_here_1 (s
);
3317 SCM_DEFINE (scm_string_delete
, "string-delete", 2, 2, 0,
3318 (SCM s
, SCM char_pred
, SCM start
, SCM end
),
3319 "Filter the string @var{s}, retaining only those characters that\n"
3320 "do not satisfy the @var{char_pred} argument. If the argument\n"
3321 "is a procedure, it is applied to each character as a predicate,\n"
3322 "if it is a character, it is tested for equality and if it is a\n"
3323 "character set, it is tested for membership.")
3324 #define FUNC_NAME s_scm_string_delete
3327 size_t cstart
, cend
;
3331 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, s
, cstr
,
3334 if (SCM_CHARP (char_pred
))
3339 chr
= SCM_CHAR (char_pred
);
3343 if (cstr
[idx
] != chr
)
3344 ls
= scm_cons (SCM_MAKE_CHAR (cstr
[idx
]), ls
);
3345 cstr
= scm_i_string_chars (s
);
3348 result
= scm_reverse_list_to_string (ls
);
3350 else if (SCM_CHARSETP (char_pred
))
3357 if (!SCM_CHARSET_GET (char_pred
, cstr
[idx
]))
3358 ls
= scm_cons (SCM_MAKE_CHAR (cstr
[idx
]), ls
);
3359 cstr
= scm_i_string_chars (s
);
3362 result
= scm_reverse_list_to_string (ls
);
3368 SCM_VALIDATE_PROC (2, char_pred
);
3372 SCM res
, ch
= SCM_MAKE_CHAR (cstr
[idx
]);
3373 res
= scm_call_1 (char_pred
, ch
);
3374 if (scm_is_false (res
))
3375 ls
= scm_cons (ch
, ls
);
3376 cstr
= scm_i_string_chars (s
);
3379 result
= scm_reverse_list_to_string (ls
);
3382 scm_remember_upto_here_1 (s
);
3388 scm_init_srfi_13 (void)
3390 #include "libguile/srfi-13.x"
3393 /* End of srfi-13.c. */