Fixed some SCM/scm_bits_t mixups.
[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>
48#include "_scm.h"
20e6290e 49#include "chars.h"
0f2d19dd 50
20e6290e 51#include "strings.h"
b6791b2e 52#include "validate.h"
0f2d19dd
JB
53\f
54
55/* {Strings}
56 */
57
3b3b36dd 58SCM_DEFINE (scm_string_p, "string?", 1, 0, 0,
6fa73e72
GB
59 (SCM obj),
60 "Returns #t iff OBJ is a string, else returns #f.")
1bbd0b84 61#define FUNC_NAME s_scm_string_p
0f2d19dd 62{
6fa73e72 63 return SCM_BOOL(SCM_STRINGP (obj));
0f2d19dd 64}
1bbd0b84 65#undef FUNC_NAME
0f2d19dd 66
3b3b36dd 67SCM_DEFINE (scm_read_only_string_p, "read-only-string?", 1, 0, 0,
1bbd0b84 68 (SCM x),
7866a09b 69 "Return true if OBJ can be read as a string,\n\n"
b380b885
MD
70 "This illustrates the difference between @code{string?} and\n"
71 "@code{read-only-string?}:\n\n"
72 "@example\n"
73 "(string? \"a string\") @result{} #t\n"
74 "(string? 'a-symbol) @result{} #f\n\n"
75 "(read-only-string? \"a string\") @result{} #t\n"
76 "(read-only-string? 'a-symbol) @result{} #t\n"
77 "@end example")
1bbd0b84 78#define FUNC_NAME s_scm_read_only_string_p
0f2d19dd 79{
1bbd0b84 80 return SCM_BOOL(SCM_ROSTRINGP (x));
0f2d19dd 81}
1bbd0b84 82#undef FUNC_NAME
0f2d19dd 83
bd9e24b3 84SCM_REGISTER_PROC (s_scm_list_to_string, "list->string", 1, 0, 0, scm_string);
1bbd0b84 85
3b3b36dd 86SCM_DEFINE (scm_string, "string", 0, 0, 1,
6fa73e72
GB
87 (SCM chrs),
88 "Returns a newly allocated string composed of the arguments, CHRS.")
1bbd0b84 89#define FUNC_NAME s_scm_string
0f2d19dd 90{
bd9e24b3
GH
91 SCM result;
92
0f2d19dd 93 {
bd9e24b3
GH
94 long i = scm_ilength (chrs);
95
96 SCM_ASSERT (i >= 0, chrs, SCM_ARGn, FUNC_NAME);
97 result = scm_makstr (i, 0);
0f2d19dd 98 }
bd9e24b3
GH
99
100 {
101 unsigned char *data = SCM_UCHARS (result);
102
103 while (SCM_NNULLP (chrs))
104 {
105 SCM elt = SCM_CAR (chrs);
106
7866a09b
GB
107 SCM_VALIDATE_CHAR (SCM_ARGn, elt);
108 *data++ = SCM_CHAR (elt);
bd9e24b3
GH
109 chrs = SCM_CDR (chrs);
110 }
111 }
112 return result;
0f2d19dd 113}
1bbd0b84 114#undef FUNC_NAME
0f2d19dd 115
0f2d19dd 116SCM
1bbd0b84 117scm_makstr (long len, int slots)
0f2d19dd
JB
118{
119 SCM s;
fee7ef83
DH
120 scm_bits_t * mem;
121
0f2d19dd
JB
122 SCM_NEWCELL (s);
123 --slots;
124 SCM_REDEFER_INTS;
fee7ef83
DH
125 mem = (scm_bits_t *) scm_must_malloc (sizeof (scm_bits_t) * (slots + 1)
126 + len + 1, "scm_makstr");
0f2d19dd
JB
127 if (slots >= 0)
128 {
129 int x;
fee7ef83 130 mem[slots] = (scm_bits_t) mem;
0f2d19dd 131 for (x = 0; x < slots; ++x)
fee7ef83 132 mem[x] = SCM_UNPACK (SCM_BOOL_F);
0f2d19dd
JB
133 }
134 SCM_SETCHARS (s, (char *) (mem + slots + 1));
135 SCM_SETLENGTH (s, len, scm_tc7_string);
136 SCM_REALLOW_INTS;
137 SCM_CHARS (s)[len] = 0;
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;
ee149d03
JB
171 SCM_SETLENGTH (answer, len, scm_tc7_string);
172 scm_done_malloc (len + 1);
173 SCM_SETCHARS (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
1bbd0b84 186scm_makfromstr (const char *src, scm_sizet len, int slots)
0f2d19dd 187{
bd9e24b3
GH
188 SCM s = scm_makstr (len, slots);
189 char *dst = SCM_CHARS (s);
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
GH
228 {
229 unsigned char *dst = SCM_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{
6fa73e72
GB
244 SCM_VALIDATE_ROSTRING (1,string);
245 return SCM_MAKINUM (SCM_ROLENGTH (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
257 SCM_VALIDATE_ROSTRING (1, str);
258 SCM_VALIDATE_INUM_COPY (2, k, idx);
259 SCM_ASSERT_RANGE (2, k, idx >= 0 && idx < SCM_ROLENGTH (str));
7866a09b 260 return SCM_MAKE_CHAR (SCM_ROUCHARS (str)[idx]);
0f2d19dd 261}
1bbd0b84 262#undef FUNC_NAME
0f2d19dd 263
3b3b36dd 264SCM_DEFINE (scm_string_set_x, "string-set!", 3, 0, 0,
6fa73e72
GB
265 (SCM str, SCM k, SCM chr),
266 "Stores CHR in element K of STRING and returns an unspecified value.\n"
267 "K must be a valid index of STR.")
1bbd0b84 268#define FUNC_NAME s_scm_string_set_x
0f2d19dd 269{
3b3b36dd
GB
270 SCM_VALIDATE_RWSTRING (1,str);
271 SCM_VALIDATE_INUM_RANGE (2,k,0,SCM_LENGTH(str));
7866a09b
GB
272 SCM_VALIDATE_CHAR (3,chr);
273 SCM_UCHARS (str)[SCM_INUM (k)] = SCM_CHAR (chr);
0f2d19dd
JB
274 return SCM_UNSPECIFIED;
275}
1bbd0b84 276#undef FUNC_NAME
0f2d19dd
JB
277
278
279
3b3b36dd 280SCM_DEFINE (scm_substring, "substring", 2, 1, 0,
1bbd0b84 281 (SCM str, SCM start, SCM end),
6fa73e72
GB
282 "Returns a newly allocated string formed from the characters\n"
283 "of STR beginning with index START (inclusive) and ending with\n"
284 "index END (exclusive).\n"
285 "STR must be a string, START and END must be exact integers satisfying:\n\n"
286 "0 <= START <= END <= (string-length STR).")
1bbd0b84 287#define FUNC_NAME s_scm_substring
0f2d19dd
JB
288{
289 long l;
3b3b36dd
GB
290 SCM_VALIDATE_ROSTRING (1,str);
291 SCM_VALIDATE_INUM (2,start);
292 SCM_VALIDATE_INUM_DEF (3,end,SCM_ROLENGTH(str));
5bff3127
GB
293 SCM_ASSERT_RANGE (2,start,SCM_INUM (start) <= SCM_ROLENGTH (str));
294 SCM_ASSERT_RANGE (2,end,SCM_INUM (end) <= SCM_ROLENGTH (str));
0f2d19dd 295 l = SCM_INUM (end)-SCM_INUM (start);
1bbd0b84 296 SCM_ASSERT (l >= 0, SCM_MAKINUM (l), SCM_OUTOFRANGE, FUNC_NAME);
0f2d19dd
JB
297 return scm_makfromstr (&SCM_ROCHARS (str)[SCM_INUM (start)], (scm_sizet)l, 0);
298}
1bbd0b84 299#undef FUNC_NAME
0f2d19dd 300
3b3b36dd 301SCM_DEFINE (scm_string_append, "string-append", 0, 0, 1,
6fa73e72
GB
302 (SCM args),
303 "Returns a newly allocated string whose characters form the\n"
304 "concatenation of the given strings, ARGS.")
1bbd0b84 305#define FUNC_NAME s_scm_string_append
0f2d19dd
JB
306{
307 SCM res;
308 register long i = 0;
309 register SCM l, s;
a65b9c80 310 register unsigned char *data;
368cf54d 311 for (l = args;SCM_CONSP (l);) {
0f2d19dd 312 s = SCM_CAR (l);
3b3b36dd 313 SCM_VALIDATE_ROSTRING (SCM_ARGn,s);
0f2d19dd
JB
314 i += SCM_ROLENGTH (s);
315 l = SCM_CDR (l);
316 }
1bbd0b84 317 SCM_ASSERT (SCM_NULLP (l), args, SCM_ARGn, FUNC_NAME);
0f2d19dd 318 res = scm_makstr (i, 0);
a65b9c80 319 data = SCM_UCHARS (res);
0f2d19dd
JB
320 for (l = args;SCM_NIMP (l);l = SCM_CDR (l)) {
321 s = SCM_CAR (l);
a65b9c80 322 for (i = 0;i<SCM_ROLENGTH (s);i++) *data++ = SCM_ROUCHARS (s)[i];
0f2d19dd
JB
323 }
324 return res;
325}
1bbd0b84 326#undef FUNC_NAME
0f2d19dd 327
3b3b36dd 328SCM_DEFINE (scm_make_shared_substring, "make-shared-substring", 1, 2, 0,
1bbd0b84 329 (SCM str, SCM frm, SCM to),
b380b885
MD
330 "Return a shared substring of @var{str}. The semantics are the same as\n"
331 "for the @code{substring} function: the shared substring returned\n"
332 "includes all of the text from @var{str} between indexes @var{start}\n"
333 "(inclusive) and @var{end} (exclusive). If @var{end} is omitted, it\n"
334 "defaults to the end of @var{str}. The shared substring returned by\n"
335 "@code{make-shared-substring} occupies the same storage space as\n"
336 "@var{str}.")
1bbd0b84 337#define FUNC_NAME s_scm_make_shared_substring
0f2d19dd
JB
338{
339 long f;
340 long t;
341 SCM answer;
342 SCM len_str;
343
3b3b36dd
GB
344 SCM_VALIDATE_ROSTRING (1,str);
345 SCM_VALIDATE_INUM_DEF_COPY (2,frm,0,f);
346 SCM_VALIDATE_INUM_DEF_COPY (3,to,SCM_ROLENGTH(str),t);
0f2d19dd 347
5bff3127
GB
348 SCM_ASSERT_RANGE (2,frm,(f >= 0));
349 SCM_ASSERT_RANGE (3,to, (f <= t) && (t <= SCM_ROLENGTH (str)));
0f2d19dd
JB
350
351 SCM_NEWCELL (answer);
352 SCM_NEWCELL (len_str);
353
354 SCM_DEFER_INTS;
355 if (SCM_SUBSTRP (str))
356 {
357 long offset;
358 offset = SCM_INUM (SCM_SUBSTR_OFFSET (str));
359 f += offset;
360 t += offset;
361 SCM_SETCAR (len_str, SCM_MAKINUM (f));
362 SCM_SETCDR (len_str, SCM_SUBSTR_STR (str));
363 SCM_SETCDR (answer, len_str);
364 SCM_SETLENGTH (answer, t - f, scm_tc7_substring);
365 }
366 else
367 {
368 SCM_SETCAR (len_str, SCM_MAKINUM (f));
369 SCM_SETCDR (len_str, str);
370 SCM_SETCDR (answer, len_str);
371 SCM_SETLENGTH (answer, t - f, scm_tc7_substring);
372 }
373 SCM_ALLOW_INTS;
374 return answer;
375}
1bbd0b84 376#undef FUNC_NAME
1cc91f1b 377
0f2d19dd
JB
378void
379scm_init_strings ()
0f2d19dd
JB
380{
381#include "strings.x"
382}
383
89e00824
ML
384
385/*
386 Local Variables:
387 c-file-style: "gnu"
388 End:
389*/