*** empty log message ***
[bpt/guile.git] / libguile / strings.c
CommitLineData
7dc6e754 1/* Copyright (C) 1995,1996,1998 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>
48#include "_scm.h"
20e6290e 49#include "chars.h"
0f2d19dd 50
20e6290e 51#include "strings.h"
1bbd0b84 52#include "scm_validate.h"
0f2d19dd
JB
53\f
54
55/* {Strings}
56 */
57
3b3b36dd 58SCM_DEFINE (scm_string_p, "string?", 1, 0, 0,
1bbd0b84
GB
59 (SCM x),
60"")
61#define FUNC_NAME s_scm_string_p
0f2d19dd
JB
62{
63 if (SCM_IMP (x))
64 return SCM_BOOL_F;
1bbd0b84 65 return SCM_BOOL(SCM_STRINGP (x));
0f2d19dd 66}
1bbd0b84 67#undef FUNC_NAME
0f2d19dd 68
3b3b36dd 69SCM_DEFINE (scm_read_only_string_p, "read-only-string?", 1, 0, 0,
1bbd0b84 70 (SCM x),
4079f87e
GB
71"Return true of OBJ can be read as a string,
72
73This illustrates the difference between @code{string?} and
74@code{read-only-string?}:
75
76@example
77(string? \"a string\") @result{} #t
78(string? 'a-symbol) @result{} #f
79
80(read-only-string? \"a string\") @result{} #t
81(read-only-string? 'a-symbol) @result{} #t
82@end example")
1bbd0b84 83#define FUNC_NAME s_scm_read_only_string_p
0f2d19dd
JB
84{
85 if (SCM_IMP (x))
86 return SCM_BOOL_F;
1bbd0b84 87 return SCM_BOOL(SCM_ROSTRINGP (x));
0f2d19dd 88}
1bbd0b84 89#undef FUNC_NAME
0f2d19dd 90
1bbd0b84 91SCM_REGISTER_PROC(s_list_to_string, "list->string", 1, 0, 0, scm_string);
1cc91f1b 92
1bbd0b84 93
3b3b36dd 94SCM_DEFINE (scm_string, "string", 0, 0, 1,
1bbd0b84
GB
95 (SCM chrs),
96"")
97#define FUNC_NAME s_scm_string
0f2d19dd
JB
98{
99 SCM res;
a65b9c80 100 register unsigned char *data;
0f2d19dd
JB
101 long i;
102 long len;
103 SCM_DEFER_INTS;
104 i = scm_ilength (chrs);
105 if (i < 0)
106 {
107 SCM_ALLOW_INTS;
1bbd0b84 108 SCM_ASSERT (0, chrs, SCM_ARG1, FUNC_NAME);
0f2d19dd
JB
109 }
110 len = 0;
111 {
112 SCM s;
113
114 for (len = 0, s = chrs; s != SCM_EOL; s = SCM_CDR (s))
115 if (SCM_ICHRP (SCM_CAR (s)))
116 len += 1;
0c95b57d 117 else if (SCM_ROSTRINGP (SCM_CAR (s)))
0f2d19dd
JB
118 len += SCM_ROLENGTH (SCM_CAR (s));
119 else
120 {
121 SCM_ALLOW_INTS;
1bbd0b84 122 SCM_ASSERT (0, s, SCM_ARG1, FUNC_NAME);
0f2d19dd
JB
123 }
124 }
125 res = scm_makstr (len, 0);
a65b9c80 126 data = SCM_UCHARS (res);
0f2d19dd
JB
127 for (;SCM_NNULLP (chrs);chrs = SCM_CDR (chrs))
128 {
129 if (SCM_ICHRP (SCM_CAR (chrs)))
130 *data++ = SCM_ICHR (SCM_CAR (chrs));
131 else
132 {
133 int l;
134 char * c;
135 l = SCM_ROLENGTH (SCM_CAR (chrs));
cdbadcac 136 c = SCM_ROCHARS (SCM_CAR (chrs));
0f2d19dd
JB
137 while (l)
138 {
139 --l;
140 *data++ = *c++;
141 }
142 }
143 }
144 SCM_ALLOW_INTS;
145 return res;
146}
1bbd0b84 147#undef FUNC_NAME
0f2d19dd 148
1cc91f1b 149
0f2d19dd 150SCM
1bbd0b84 151scm_makstr (long len, int slots)
0f2d19dd
JB
152{
153 SCM s;
154 SCM * mem;
155 SCM_NEWCELL (s);
156 --slots;
157 SCM_REDEFER_INTS;
158 mem = (SCM *)scm_must_malloc (sizeof (SCM) * (slots + 1) + len + 1,
1bbd0b84 159 "scm_makstr");
0f2d19dd
JB
160 if (slots >= 0)
161 {
162 int x;
163 mem[slots] = (SCM)mem;
164 for (x = 0; x < slots; ++x)
165 mem[x] = SCM_BOOL_F;
166 }
167 SCM_SETCHARS (s, (char *) (mem + slots + 1));
168 SCM_SETLENGTH (s, len, scm_tc7_string);
169 SCM_REALLOW_INTS;
170 SCM_CHARS (s)[len] = 0;
171 return s;
172}
173
174/* converts C scm_array of strings to SCM scm_list of strings. */
175/* If argc < 0, a null terminated scm_array is assumed. */
1cc91f1b 176
0f2d19dd 177SCM
1bbd0b84 178scm_makfromstrs (int argc, char **argv)
0f2d19dd
JB
179{
180 int i = argc;
181 SCM lst = SCM_EOL;
182 if (0 > i)
183 for (i = 0; argv[i]; i++);
184 while (i--)
185 lst = scm_cons (scm_makfromstr (argv[i], (scm_sizet) strlen (argv[i]), 0), lst);
186 return lst;
187}
188
189
ee149d03
JB
190/* This function must only be applied to memory obtained via malloc,
191 since the GC is going to apply `free' to it when the string is
192 dropped.
193
194 Also, s[len] must be `\0', since we promise that strings are
195 null-terminated. Perhaps we could handle non-null-terminated
196 strings by claiming they're shared substrings of a string we just
197 made up. */
0f2d19dd 198SCM
ee149d03 199scm_take_str (char *s, int len)
0f2d19dd
JB
200{
201 SCM answer;
202 SCM_NEWCELL (answer);
203 SCM_DEFER_INTS;
ee149d03
JB
204 SCM_SETLENGTH (answer, len, scm_tc7_string);
205 scm_done_malloc (len + 1);
206 SCM_SETCHARS (answer, s);
0f2d19dd
JB
207 SCM_ALLOW_INTS;
208 return answer;
209}
210
ee149d03
JB
211/* `s' must be a malloc'd string. See scm_take_str. */
212SCM
213scm_take0str (char *s)
214{
215 return scm_take_str (s, strlen (s));
216}
217
1cc91f1b 218
0f2d19dd 219SCM
1bbd0b84 220scm_makfromstr (const char *src, scm_sizet len, int slots)
0f2d19dd
JB
221{
222 SCM s;
223 register char *dst;
224 s = scm_makstr ((long) len, slots);
225 dst = SCM_CHARS (s);
226 while (len--)
227 *dst++ = *src++;
228 return s;
229}
230
231
1cc91f1b 232
0f2d19dd 233SCM
1bbd0b84 234scm_makfrom0str (const char *src)
0f2d19dd
JB
235{
236 if (!src) return SCM_BOOL_F;
237 return scm_makfromstr (src, (scm_sizet) strlen (src), 0);
238}
239
1cc91f1b 240
0f2d19dd 241SCM
1bbd0b84 242scm_makfrom0str_opt (const char *src)
0f2d19dd
JB
243{
244 return scm_makfrom0str (src);
245}
246
247
248
249
3b3b36dd 250SCM_DEFINE (scm_make_string, "make-string", 1, 1, 0,
1bbd0b84
GB
251 (SCM k, SCM chr),
252"")
253#define FUNC_NAME s_scm_make_string
0f2d19dd
JB
254{
255 SCM res;
0f2d19dd 256 register long i;
3b3b36dd 257 SCM_VALIDATE_INUM_MIN_COPY (1,k,0,i);
0f2d19dd 258 res = scm_makstr (i, 0);
6c951427 259 if (!SCM_UNBNDP (chr))
0f2d19dd 260 {
9a8351bc 261 SCM_VALIDATE_ICHR (2,chr);
6c951427
GH
262 {
263 unsigned char *dst = SCM_UCHARS (res);
264 char c = SCM_ICHR (chr);
265
266 memset (dst, c, i);
267 }
0f2d19dd
JB
268 }
269 return res;
270}
1bbd0b84 271#undef FUNC_NAME
0f2d19dd 272
3b3b36dd 273SCM_DEFINE (scm_string_length, "string-length", 1, 0, 0,
1bbd0b84
GB
274 (SCM str),
275"")
276#define FUNC_NAME s_scm_string_length
0f2d19dd 277{
3b3b36dd 278 SCM_VALIDATE_ROSTRING (1,str);
0f2d19dd
JB
279 return SCM_MAKINUM (SCM_ROLENGTH (str));
280}
1bbd0b84 281#undef FUNC_NAME
0f2d19dd 282
3b3b36dd 283SCM_DEFINE (scm_string_ref, "string-ref", 1, 1, 0,
1bbd0b84
GB
284 (SCM str, SCM k),
285"")
286#define FUNC_NAME s_scm_string_ref
0f2d19dd 287{
3b3b36dd
GB
288 SCM_VALIDATE_ROSTRING (1,str);
289 SCM_VALIDATE_INUM_DEF (2,k,0);
5bff3127 290 SCM_ASSERT_RANGE (2,k,SCM_INUM (k) < SCM_ROLENGTH (str) && SCM_INUM (k) >= 0);
a65b9c80 291 return SCM_MAKICHR (SCM_ROUCHARS (str)[SCM_INUM (k)]);
0f2d19dd 292}
1bbd0b84 293#undef FUNC_NAME
0f2d19dd 294
3b3b36dd 295SCM_DEFINE (scm_string_set_x, "string-set!", 3, 0, 0,
1bbd0b84
GB
296 (SCM str, SCM k, SCM chr),
297"")
298#define FUNC_NAME s_scm_string_set_x
0f2d19dd 299{
3b3b36dd
GB
300 SCM_VALIDATE_RWSTRING (1,str);
301 SCM_VALIDATE_INUM_RANGE (2,k,0,SCM_LENGTH(str));
9a8351bc 302 SCM_VALIDATE_ICHR (3,chr);
a65b9c80 303 SCM_UCHARS (str)[SCM_INUM (k)] = SCM_ICHR (chr);
0f2d19dd
JB
304 return SCM_UNSPECIFIED;
305}
1bbd0b84 306#undef FUNC_NAME
0f2d19dd
JB
307
308
309
3b3b36dd 310SCM_DEFINE (scm_substring, "substring", 2, 1, 0,
1bbd0b84
GB
311 (SCM str, SCM start, SCM end),
312"")
313#define FUNC_NAME s_scm_substring
0f2d19dd
JB
314{
315 long l;
3b3b36dd
GB
316 SCM_VALIDATE_ROSTRING (1,str);
317 SCM_VALIDATE_INUM (2,start);
318 SCM_VALIDATE_INUM_DEF (3,end,SCM_ROLENGTH(str));
5bff3127
GB
319 SCM_ASSERT_RANGE (2,start,SCM_INUM (start) <= SCM_ROLENGTH (str));
320 SCM_ASSERT_RANGE (2,end,SCM_INUM (end) <= SCM_ROLENGTH (str));
0f2d19dd 321 l = SCM_INUM (end)-SCM_INUM (start);
1bbd0b84 322 SCM_ASSERT (l >= 0, SCM_MAKINUM (l), SCM_OUTOFRANGE, FUNC_NAME);
0f2d19dd
JB
323 return scm_makfromstr (&SCM_ROCHARS (str)[SCM_INUM (start)], (scm_sizet)l, 0);
324}
1bbd0b84 325#undef FUNC_NAME
0f2d19dd 326
3b3b36dd 327SCM_DEFINE (scm_string_append, "string-append", 0, 0, 1,
1bbd0b84
GB
328 (SCM args),
329"")
330#define FUNC_NAME s_scm_string_append
0f2d19dd
JB
331{
332 SCM res;
333 register long i = 0;
334 register SCM l, s;
a65b9c80 335 register unsigned char *data;
368cf54d 336 for (l = args;SCM_CONSP (l);) {
0f2d19dd 337 s = SCM_CAR (l);
3b3b36dd 338 SCM_VALIDATE_ROSTRING (SCM_ARGn,s);
0f2d19dd
JB
339 i += SCM_ROLENGTH (s);
340 l = SCM_CDR (l);
341 }
1bbd0b84 342 SCM_ASSERT (SCM_NULLP (l), args, SCM_ARGn, FUNC_NAME);
0f2d19dd 343 res = scm_makstr (i, 0);
a65b9c80 344 data = SCM_UCHARS (res);
0f2d19dd
JB
345 for (l = args;SCM_NIMP (l);l = SCM_CDR (l)) {
346 s = SCM_CAR (l);
a65b9c80 347 for (i = 0;i<SCM_ROLENGTH (s);i++) *data++ = SCM_ROUCHARS (s)[i];
0f2d19dd
JB
348 }
349 return res;
350}
1bbd0b84 351#undef FUNC_NAME
0f2d19dd 352
3b3b36dd 353SCM_DEFINE (scm_make_shared_substring, "make-shared-substring", 1, 2, 0,
1bbd0b84 354 (SCM str, SCM frm, SCM to),
4079f87e
GB
355"Return a shared substring of @var{str}. The semantics are the same as
356for the @code{substring} function: the shared substring returned
357includes all of the text from @var{str} between indexes @var{start}
358(inclusive) and @var{end} (exclusive). If @var{end} is omitted, it
359defaults to the end of @var{str}. The shared substring returned by
360@code{make-shared-substring} occupies the same storage space as
361@var{str}.")
1bbd0b84 362#define FUNC_NAME s_scm_make_shared_substring
0f2d19dd
JB
363{
364 long f;
365 long t;
366 SCM answer;
367 SCM len_str;
368
3b3b36dd
GB
369 SCM_VALIDATE_ROSTRING (1,str);
370 SCM_VALIDATE_INUM_DEF_COPY (2,frm,0,f);
371 SCM_VALIDATE_INUM_DEF_COPY (3,to,SCM_ROLENGTH(str),t);
0f2d19dd 372
5bff3127
GB
373 SCM_ASSERT_RANGE (2,frm,(f >= 0));
374 SCM_ASSERT_RANGE (3,to, (f <= t) && (t <= SCM_ROLENGTH (str)));
0f2d19dd
JB
375
376 SCM_NEWCELL (answer);
377 SCM_NEWCELL (len_str);
378
379 SCM_DEFER_INTS;
380 if (SCM_SUBSTRP (str))
381 {
382 long offset;
383 offset = SCM_INUM (SCM_SUBSTR_OFFSET (str));
384 f += offset;
385 t += offset;
386 SCM_SETCAR (len_str, SCM_MAKINUM (f));
387 SCM_SETCDR (len_str, SCM_SUBSTR_STR (str));
388 SCM_SETCDR (answer, len_str);
389 SCM_SETLENGTH (answer, t - f, scm_tc7_substring);
390 }
391 else
392 {
393 SCM_SETCAR (len_str, SCM_MAKINUM (f));
394 SCM_SETCDR (len_str, str);
395 SCM_SETCDR (answer, len_str);
396 SCM_SETLENGTH (answer, t - f, scm_tc7_substring);
397 }
398 SCM_ALLOW_INTS;
399 return answer;
400}
1bbd0b84 401#undef FUNC_NAME
1cc91f1b 402
0f2d19dd
JB
403void
404scm_init_strings ()
0f2d19dd
JB
405{
406#include "strings.x"
407}
408