* SCM_SETCHARS deprecated.
[bpt/guile.git] / libguile / strings.c
CommitLineData
bd9e24b3 1/* Copyright (C) 1995,1996,1998,2000 Free Software Foundation, Inc.
0f2d19dd
JB
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2, or (at your option)
6 * any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this software; see the file COPYING. If not, write to
82892bed
JB
15 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
16 * Boston, MA 02111-1307 USA
0f2d19dd
JB
17 *
18 * As a special exception, the Free Software Foundation gives permission
19 * for additional uses of the text contained in its release of GUILE.
20 *
21 * The exception is that, if you link the GUILE library with other files
22 * to produce an executable, this does not by itself cause the
23 * resulting executable to be covered by the GNU General Public License.
24 * Your use of that executable is in no way restricted on account of
25 * linking the GUILE library code into it.
26 *
27 * This exception does not however invalidate any other reasons why
28 * the executable file might be covered by the GNU General Public License.
29 *
30 * This exception applies only to the code released by the
31 * Free Software Foundation under the name GUILE. If you copy
32 * code from other Free Software Foundation releases into a copy of
33 * GUILE, as the General Public License permits, the exception does
34 * not apply to the code that you add in this way. To avoid misleading
35 * anyone as to the status of such modified files, you must delete
36 * this exception notice from them.
37 *
38 * If you write modifications of your own for GUILE, it is your choice
39 * whether to permit this exception to apply to your modifications.
82892bed 40 * If you do not wish that, delete this exception notice. */
1bbd0b84
GB
41
42/* Software engineering face-lift by Greg J. Badros, 11-Dec-1999,
43 gjb@cs.washington.edu, http://www.cs.washington.edu/homes/gjb */
44
0f2d19dd
JB
45\f
46
47#include <stdio.h>
faf2c9d7
MD
48#include <string.h>
49
a0599745
MD
50#include "libguile/_scm.h"
51#include "libguile/chars.h"
0f2d19dd 52
a0599745
MD
53#include "libguile/strings.h"
54#include "libguile/validate.h"
0f2d19dd
JB
55\f
56
57/* {Strings}
58 */
59
3b3b36dd 60SCM_DEFINE (scm_string_p, "string?", 1, 0, 0,
6fa73e72
GB
61 (SCM obj),
62 "Returns #t iff OBJ is a string, else returns #f.")
1bbd0b84 63#define FUNC_NAME s_scm_string_p
0f2d19dd 64{
e53cc817 65 return SCM_BOOL (SCM_STRINGP (obj));
0f2d19dd 66}
1bbd0b84 67#undef FUNC_NAME
0f2d19dd 68
e53cc817
MD
69#if SCM_DEBUG_DEPRECATED == 0
70
71/* The concept of read-only strings will disappear in next release
72 * of Guile.
73 */
74
3b3b36dd 75SCM_DEFINE (scm_read_only_string_p, "read-only-string?", 1, 0, 0,
1bbd0b84 76 (SCM x),
7866a09b 77 "Return true if OBJ can be read as a string,\n\n"
b380b885
MD
78 "This illustrates the difference between @code{string?} and\n"
79 "@code{read-only-string?}:\n\n"
80 "@example\n"
81 "(string? \"a string\") @result{} #t\n"
82 "(string? 'a-symbol) @result{} #f\n\n"
83 "(read-only-string? \"a string\") @result{} #t\n"
84 "(read-only-string? 'a-symbol) @result{} #t\n"
85 "@end example")
1bbd0b84 86#define FUNC_NAME s_scm_read_only_string_p
0f2d19dd 87{
1bbd0b84 88 return SCM_BOOL(SCM_ROSTRINGP (x));
0f2d19dd 89}
1bbd0b84 90#undef FUNC_NAME
0f2d19dd 91
e53cc817
MD
92#endif /* DEPRECATED */
93
bd9e24b3 94SCM_REGISTER_PROC (s_scm_list_to_string, "list->string", 1, 0, 0, scm_string);
1bbd0b84 95
3b3b36dd 96SCM_DEFINE (scm_string, "string", 0, 0, 1,
6fa73e72 97 (SCM chrs),
11768c04 98 "@deffnx primitive list->string chrs\n"
6fa73e72 99 "Returns a newly allocated string composed of the arguments, CHRS.")
1bbd0b84 100#define FUNC_NAME s_scm_string
0f2d19dd 101{
bd9e24b3
GH
102 SCM result;
103
0f2d19dd 104 {
bd9e24b3
GH
105 long i = scm_ilength (chrs);
106
107 SCM_ASSERT (i >= 0, chrs, SCM_ARGn, FUNC_NAME);
108 result = scm_makstr (i, 0);
0f2d19dd 109 }
bd9e24b3
GH
110
111 {
322ac0c5 112 unsigned char *data = SCM_STRING_UCHARS (result);
bd9e24b3
GH
113
114 while (SCM_NNULLP (chrs))
115 {
116 SCM elt = SCM_CAR (chrs);
117
7866a09b
GB
118 SCM_VALIDATE_CHAR (SCM_ARGn, elt);
119 *data++ = SCM_CHAR (elt);
bd9e24b3
GH
120 chrs = SCM_CDR (chrs);
121 }
122 }
123 return result;
0f2d19dd 124}
1bbd0b84 125#undef FUNC_NAME
0f2d19dd 126
0f2d19dd 127SCM
28b06554 128scm_makstr (long len, int dummy)
0f2d19dd
JB
129{
130 SCM s;
28b06554 131 char *mem = (char *) scm_must_malloc (len + 1, "scm_makstr");
fee7ef83 132
28b06554 133 mem[len] = 0;
0f2d19dd 134 SCM_NEWCELL (s);
6a0476fd 135 SCM_SET_STRING_CHARS (s, mem);
93778877 136 SCM_SET_STRING_LENGTH (s, len);
28b06554 137
0f2d19dd
JB
138 return s;
139}
140
141/* converts C scm_array of strings to SCM scm_list of strings. */
142/* If argc < 0, a null terminated scm_array is assumed. */
1cc91f1b 143
0f2d19dd 144SCM
1bbd0b84 145scm_makfromstrs (int argc, char **argv)
0f2d19dd
JB
146{
147 int i = argc;
148 SCM lst = SCM_EOL;
149 if (0 > i)
150 for (i = 0; argv[i]; i++);
151 while (i--)
152 lst = scm_cons (scm_makfromstr (argv[i], (scm_sizet) strlen (argv[i]), 0), lst);
153 return lst;
154}
155
156
ee149d03
JB
157/* This function must only be applied to memory obtained via malloc,
158 since the GC is going to apply `free' to it when the string is
159 dropped.
160
161 Also, s[len] must be `\0', since we promise that strings are
162 null-terminated. Perhaps we could handle non-null-terminated
163 strings by claiming they're shared substrings of a string we just
164 made up. */
0f2d19dd 165SCM
ee149d03 166scm_take_str (char *s, int len)
0f2d19dd
JB
167{
168 SCM answer;
169 SCM_NEWCELL (answer);
170 SCM_DEFER_INTS;
93778877 171 SCM_SET_STRING_LENGTH (answer, len);
ee149d03 172 scm_done_malloc (len + 1);
6a0476fd 173 SCM_SET_STRING_CHARS (answer, s);
0f2d19dd
JB
174 SCM_ALLOW_INTS;
175 return answer;
176}
177
ee149d03
JB
178/* `s' must be a malloc'd string. See scm_take_str. */
179SCM
180scm_take0str (char *s)
181{
182 return scm_take_str (s, strlen (s));
183}
184
0f2d19dd 185SCM
28b06554 186scm_makfromstr (const char *src, scm_sizet len, int dummy)
0f2d19dd 187{
28b06554 188 SCM s = scm_makstr (len, 0);
86c991c2 189 char *dst = SCM_STRING_CHARS (s);
bd9e24b3 190
0f2d19dd
JB
191 while (len--)
192 *dst++ = *src++;
193 return s;
194}
195
0f2d19dd 196SCM
1bbd0b84 197scm_makfrom0str (const char *src)
0f2d19dd
JB
198{
199 if (!src) return SCM_BOOL_F;
200 return scm_makfromstr (src, (scm_sizet) strlen (src), 0);
201}
202
1cc91f1b 203
0f2d19dd 204SCM
1bbd0b84 205scm_makfrom0str_opt (const char *src)
0f2d19dd
JB
206{
207 return scm_makfrom0str (src);
208}
209
210
211
212
3b3b36dd 213SCM_DEFINE (scm_make_string, "make-string", 1, 1, 0,
6fa73e72
GB
214 (SCM k, SCM chr),
215 "Returns a newly allocated string of\n"
216 "length K. If CHR is given, then all elements of the string\n"
217 "are initialized to CHR, otherwise the contents of the\n"
b450f070 218 "STRING are unspecified.\n")
1bbd0b84 219#define FUNC_NAME s_scm_make_string
0f2d19dd
JB
220{
221 SCM res;
0f2d19dd 222 register long i;
3b3b36dd 223 SCM_VALIDATE_INUM_MIN_COPY (1,k,0,i);
0f2d19dd 224 res = scm_makstr (i, 0);
6c951427 225 if (!SCM_UNBNDP (chr))
0f2d19dd 226 {
7866a09b 227 SCM_VALIDATE_CHAR (2,chr);
6c951427 228 {
322ac0c5 229 unsigned char *dst = SCM_STRING_UCHARS (res);
7866a09b 230 char c = SCM_CHAR (chr);
6c951427
GH
231
232 memset (dst, c, i);
233 }
0f2d19dd
JB
234 }
235 return res;
236}
1bbd0b84 237#undef FUNC_NAME
0f2d19dd 238
3b3b36dd 239SCM_DEFINE (scm_string_length, "string-length", 1, 0, 0,
6fa73e72
GB
240 (SCM string),
241 "Returns the number of characters in STRING")
1bbd0b84 242#define FUNC_NAME s_scm_string_length
0f2d19dd 243{
d1ca2c64 244 SCM_VALIDATE_STRING (1, string);
bfa974f0 245 return SCM_MAKINUM (SCM_STRING_LENGTH (string));
0f2d19dd 246}
1bbd0b84 247#undef FUNC_NAME
0f2d19dd 248
bd9e24b3 249SCM_DEFINE (scm_string_ref, "string-ref", 2, 0, 0,
6fa73e72
GB
250 (SCM str, SCM k),
251 "Returns character K of STR using zero-origin indexing.\n"
252 "K must be a valid index of STR.")
1bbd0b84 253#define FUNC_NAME s_scm_string_ref
0f2d19dd 254{
bd9e24b3
GH
255 int idx;
256
d1ca2c64 257 SCM_VALIDATE_STRING (1, str);
bd9e24b3 258 SCM_VALIDATE_INUM_COPY (2, k, idx);
d1ca2c64 259 SCM_ASSERT_RANGE (2, k, idx >= 0 && idx < SCM_STRING_LENGTH (str));
34f0f2b8 260 return SCM_MAKE_CHAR (SCM_STRING_UCHARS (str)[idx]);
0f2d19dd 261}
1bbd0b84 262#undef FUNC_NAME
0f2d19dd 263
f0942910 264
3b3b36dd 265SCM_DEFINE (scm_string_set_x, "string-set!", 3, 0, 0,
6fa73e72
GB
266 (SCM str, SCM k, SCM chr),
267 "Stores CHR in element K of STRING and returns an unspecified value.\n"
268 "K must be a valid index of STR.")
1bbd0b84 269#define FUNC_NAME s_scm_string_set_x
0f2d19dd 270{
f0942910
DH
271#if (SCM_DEBUG_DEPRECATED == 0)
272 SCM_VALIDATE_RWSTRING (1, str);
273#else
274 SCM_VALIDATE_STRING (1, str);
275#endif
bfa974f0 276 SCM_VALIDATE_INUM_RANGE (2,k,0,SCM_STRING_LENGTH(str));
7866a09b 277 SCM_VALIDATE_CHAR (3,chr);
322ac0c5 278 SCM_STRING_UCHARS (str)[SCM_INUM (k)] = SCM_CHAR (chr);
0f2d19dd
JB
279 return SCM_UNSPECIFIED;
280}
1bbd0b84 281#undef FUNC_NAME
0f2d19dd
JB
282
283
3b3b36dd 284SCM_DEFINE (scm_substring, "substring", 2, 1, 0,
1bbd0b84 285 (SCM str, SCM start, SCM end),
6fa73e72
GB
286 "Returns a newly allocated string formed from the characters\n"
287 "of STR beginning with index START (inclusive) and ending with\n"
288 "index END (exclusive).\n"
289 "STR must be a string, START and END must be exact integers satisfying:\n\n"
290 "0 <= START <= END <= (string-length STR).")
1bbd0b84 291#define FUNC_NAME s_scm_substring
0f2d19dd 292{
685c0d71
DH
293 long int from;
294 long int to;
295
d1ca2c64 296 SCM_VALIDATE_STRING (1, str);
685c0d71 297 SCM_VALIDATE_INUM (2, start);
d1ca2c64 298 SCM_VALIDATE_INUM_DEF (3, end, SCM_STRING_LENGTH (str));
685c0d71
DH
299
300 from = SCM_INUM (start);
d1ca2c64 301 SCM_ASSERT_RANGE (2, start, 0 <= from && from <= SCM_STRING_LENGTH (str));
685c0d71 302 to = SCM_INUM (end);
d1ca2c64 303 SCM_ASSERT_RANGE (3, end, from <= to && to <= SCM_STRING_LENGTH (str));
685c0d71 304
34f0f2b8 305 return scm_makfromstr (&SCM_STRING_CHARS (str)[from], (scm_sizet) (to - from), 0);
0f2d19dd 306}
1bbd0b84 307#undef FUNC_NAME
0f2d19dd 308
685c0d71 309
3b3b36dd 310SCM_DEFINE (scm_string_append, "string-append", 0, 0, 1,
6fa73e72
GB
311 (SCM args),
312 "Returns a newly allocated string whose characters form the\n"
313 "concatenation of the given strings, ARGS.")
1bbd0b84 314#define FUNC_NAME s_scm_string_append
0f2d19dd
JB
315{
316 SCM res;
317 register long i = 0;
318 register SCM l, s;
a65b9c80 319 register unsigned char *data;
af45e3b0
DH
320
321 SCM_VALIDATE_REST_ARGUMENT (args);
322 for (l = args; !SCM_NULLP (l); l = SCM_CDR (l)) {
0f2d19dd 323 s = SCM_CAR (l);
d1ca2c64
DH
324 SCM_VALIDATE_STRING (SCM_ARGn,s);
325 i += SCM_STRING_LENGTH (s);
0f2d19dd 326 }
0f2d19dd 327 res = scm_makstr (i, 0);
322ac0c5 328 data = SCM_STRING_UCHARS (res);
0f2d19dd
JB
329 for (l = args;SCM_NIMP (l);l = SCM_CDR (l)) {
330 s = SCM_CAR (l);
34f0f2b8 331 for (i = 0;i<SCM_STRING_LENGTH (s);i++) *data++ = SCM_STRING_UCHARS (s)[i];
0f2d19dd
JB
332 }
333 return res;
334}
1bbd0b84 335#undef FUNC_NAME
0f2d19dd 336
e53cc817
MD
337#if SCM_DEBUG_DEPRECATED == 0
338
339/* Explicit shared substrings will disappear from Guile.
340 *
341 * Instead, "normal" strings will be implemented using sharing
342 * internally, combined with a copy-on-write strategy.
343 */
344
3b3b36dd 345SCM_DEFINE (scm_make_shared_substring, "make-shared-substring", 1, 2, 0,
1bbd0b84 346 (SCM str, SCM frm, SCM to),
b380b885
MD
347 "Return a shared substring of @var{str}. The semantics are the same as\n"
348 "for the @code{substring} function: the shared substring returned\n"
349 "includes all of the text from @var{str} between indexes @var{start}\n"
350 "(inclusive) and @var{end} (exclusive). If @var{end} is omitted, it\n"
351 "defaults to the end of @var{str}. The shared substring returned by\n"
352 "@code{make-shared-substring} occupies the same storage space as\n"
353 "@var{str}.")
1bbd0b84 354#define FUNC_NAME s_scm_make_shared_substring
0f2d19dd
JB
355{
356 long f;
357 long t;
358 SCM answer;
359 SCM len_str;
360
3b3b36dd
GB
361 SCM_VALIDATE_ROSTRING (1,str);
362 SCM_VALIDATE_INUM_DEF_COPY (2,frm,0,f);
363 SCM_VALIDATE_INUM_DEF_COPY (3,to,SCM_ROLENGTH(str),t);
0f2d19dd 364
5bff3127
GB
365 SCM_ASSERT_RANGE (2,frm,(f >= 0));
366 SCM_ASSERT_RANGE (3,to, (f <= t) && (t <= SCM_ROLENGTH (str)));
0f2d19dd
JB
367
368 SCM_NEWCELL (answer);
369 SCM_NEWCELL (len_str);
370
371 SCM_DEFER_INTS;
372 if (SCM_SUBSTRP (str))
373 {
374 long offset;
375 offset = SCM_INUM (SCM_SUBSTR_OFFSET (str));
376 f += offset;
377 t += offset;
378 SCM_SETCAR (len_str, SCM_MAKINUM (f));
379 SCM_SETCDR (len_str, SCM_SUBSTR_STR (str));
380 SCM_SETCDR (answer, len_str);
381 SCM_SETLENGTH (answer, t - f, scm_tc7_substring);
382 }
383 else
384 {
385 SCM_SETCAR (len_str, SCM_MAKINUM (f));
386 SCM_SETCDR (len_str, str);
387 SCM_SETCDR (answer, len_str);
388 SCM_SETLENGTH (answer, t - f, scm_tc7_substring);
389 }
390 SCM_ALLOW_INTS;
391 return answer;
392}
1bbd0b84 393#undef FUNC_NAME
1cc91f1b 394
e53cc817
MD
395#endif /* DEPRECATED */
396
0f2d19dd
JB
397void
398scm_init_strings ()
0f2d19dd 399{
8dc9439f 400#ifndef SCM_MAGIC_SNARFER
a0599745 401#include "libguile/strings.x"
8dc9439f 402#endif
0f2d19dd
JB
403}
404
89e00824
ML
405
406/*
407 Local Variables:
408 c-file-style: "gnu"
409 End:
410*/