20
20
#include <string.h>
21
21
#include <ecl/ecl-inl.h>
24
do_make_base_string(cl_index s, int code)
26
cl_object x = cl_alloc_simple_base_string(s);
28
for (i = 0; i < s; i++)
29
x->base_string.self[i] = code;
25
/* TODO: add a special variable to allow make-string to default to base-char rather than character. */
26
/* should be @'character' -- FIXME */
35
do_make_string(cl_index s, cl_index code)
37
cl_object x = cl_alloc_simple_extended_string(s);
38
cl_object c = CODE_CHAR(code);
40
for (i = 0; i < s; i++)
41
x->string.self[i] = c;
45
#define do_make_string do_make_base_string
28
48
@(defun make_string (size &key (initial_element CODE_CHAR(' '))
29
(element_type @'character')
49
(element_type @'character'))
33
/* INV: char_code() checks the type of initial_element() */
34
code = char_code(initial_element);
35
s = object_to_index(size);
37
/* this code should use subtypep */
38
/* handle base-char strings */
53
s = ecl_to_index(size);
54
/* INV: ecl_[base_]char_code() checks the type of initial_element() */
39
55
if (element_type == @'base-char' || element_type == @'standard-char') {
40
x = cl_alloc_simple_base_string(s);
41
for (i = 0; i < s; i++)
42
x->base_string.self[i] = code;
46
if (element_type != @'character'
47
&& (funcall(3, @'subtypep', element_type, @'character') == Cnil))
48
FEerror("The type ~S is not a valid string char type.", 1, element_type);
50
x = cl_alloc_simple_extended_string(s);
51
for (i = 0; i < s; i++)
52
x->string.self[i] = CODE_CHAR(code);
56
@(defun make_string (size &key (initial_element CODE_CHAR(' '))
57
(element_type @'character')
61
if (element_type != @'character'
62
&& element_type != @'base-char'
63
&& element_type != @'standard-char') {
64
if (funcall(3, @'subtypep', element_type, @'character') == Cnil)
65
FEerror("The type ~S is not a valid string char type.",
68
/* INV: char_code() checks the type of initial_element() */
69
code = char_code(initial_element);
70
s = object_to_index(size);
71
x = cl_alloc_simple_base_string(s);
72
for (i = 0; i < s; i++)
73
x->base_string.self[i] = code;
56
int code = ecl_base_char_code(initial_element);
57
x = do_make_base_string(s, code);
58
} else if (element_type == @'character') {
59
cl_index code = ecl_char_code(initial_element);
60
x = do_make_string(s, code);
61
} else if (funcall(3, @'subtypep', element_type, @'base-char') == Ct) {
62
int code = ecl_base_char_code(initial_element);
63
x = do_make_base_string(s, code);
64
} else if (funcall(3, @'subtypep', element_type, @'character') == Ct) {
65
cl_index code = ecl_char_code(initial_element);
66
x = do_make_string(s, code);
68
FEerror("The type ~S is not a valid string char type.",
79
75
cl_alloc_simple_base_string(cl_index length)
282
303
cl_char(cl_object object, cl_object index)
284
cl_index position = object_to_index(index);
305
cl_index position = ecl_to_index(index);
306
@(return CODE_CHAR(ecl_char(object, position)))
310
ecl_char(cl_object object, cl_index index)
285
312
/* CHAR bypasses fill pointers when accessing strings */
287
314
switch(type_of(object)) {
288
315
#ifdef ECL_UNICODE
290
if (position >= object->string.dim)
291
illegal_index(object, index);
292
@(return object->string.self[position])
317
if (index >= object->string.dim)
318
FEillegal_index(object, MAKE_FIXNUM(index));
319
return CHAR_CODE(object->string.self[index]);
294
321
case t_base_string:
295
if (position >= object->base_string.dim)
296
illegal_index(object, index);
297
@(return CODE_CHAR(object->base_string.self[position]))
322
if (index >= object->base_string.dim)
323
FEillegal_index(object, MAKE_FIXNUM(index));
324
return object->base_string.self[index];
299
FEtype_error_string(object);
326
object = ecl_type_error(@'char',"",object,@'string');
304
332
si_char_set(cl_object object, cl_object index, cl_object value)
306
cl_index position = object_to_index(index);
334
cl_index position = ecl_to_index(index);
335
cl_index c = ecl_char_code(value);
336
ecl_char_set(object, position, c);
341
ecl_char_set(cl_object object, cl_index index, cl_index value)
308
344
/* CHAR bypasses fill pointers when accessing strings */
309
345
switch(type_of(object)) {
310
346
#ifdef ECL_UNICODE
312
if (position >= object->string.dim)
313
illegal_index(object, index);
314
if (!CHARACTERP(value)) FEtype_error_character(value);
315
object->string.self[position] = value;
316
@(return object->string.self[position])
348
if (index >= object->string.dim)
349
FEillegal_index(object, MAKE_FIXNUM(index));
350
object->string.self[index] = CODE_CHAR(value);
318
353
case t_base_string:
319
if (position >= object->base_string.dim)
320
illegal_index(object, index);
321
/* INV: char_code() checks type of value */
322
object->base_string.self[position] = char_code(value);
354
if (index >= object->base_string.dim)
355
FEillegal_index(object, MAKE_FIXNUM(index));
356
/* INV: ecl_char_code() checks type of value */
357
object->base_string.self[index] = value;
325
FEtype_error_string(object);
360
object = ecl_type_error(@'si::char-set', "", object, @'string');
357
393
#ifdef ECL_UNICODE
359
compare_extended(cl_object *s1, cl_index l1, cl_object *s2, cl_index l2,
360
int case_sensitive, cl_index *m)
363
for (l = 0; l < l1; l++, s1++, s2++) {
364
if (l == l2) { /* s1 is longer than s2, therefore s2 < s1 */
370
if (!case_sensitive) {
377
} else if (c1 > c2) {
385
else { /* s1 is shorter than s2, hence s1 < s2 */
393
compare_mixed(cl_object *s1, cl_index l1, char *s2, cl_index l2,
394
int case_sensitive, cl_index *m)
397
for (l = 0; l < l1; l++, s1++, s2++) {
398
if (l == l2) { /* s1 is longer than s2, therefore s2 < s1 */
404
if (!case_sensitive) {
411
} else if (c1 > c2) {
419
else { /* s1 is shorter than s2, hence s1 < s2 */
395
compare_strings(cl_object string1, cl_index s1, cl_index e1,
396
cl_object string2, cl_index s2, cl_index e2,
397
int case_sensitive, cl_index *m)
400
for (; s1 < e1; s1++, s2++) {
401
if (s2 >= e2) { /* s1 is longer than s2, therefore s2 < s1 */
405
c1 = ecl_char(string1, s1);
406
c2 = ecl_char(string2, s2);
407
if (!case_sensitive) {
414
} else if (c1 > c2) {
422
} else { /* s1 is shorter than s2, hence s1 < s2 */
564
562
cl_index s1, e1, s2, e2;
567
566
string1 = cl_string(string1);
568
567
string2 = cl_string(string2);
569
568
get_string_start_end(string1, start1, end1, &s1, &e1);
570
569
get_string_start_end(string2, start2, end2, &s2, &e2);
571
570
if (e1 - s1 != e2 - s2)
573
572
#ifdef ECL_UNICODE
574
switch(type_of(string1)) {
576
switch(type_of(string2)) {
578
output = compare_extended(string1->string.self + s1, e1 - s1,
579
string2->string.self + s2, e2 - s2,
583
output = compare_mixed(string1->string.self + s1, e1 - s1,
584
string2->base_string.self + s2, e2 - s2,
588
FEtype_error_string(string2);
592
switch(type_of(string2)) {
594
output = compare_mixed(string2->string.self + s2, e2 - s2,
595
string1->base_string.self + s1, e1 - s1,
599
output = compare_base(string1->base_string.self + s1, e1 - s1,
600
string2->base_string.self + s2, e2 - s2,
604
FEtype_error_string(string2);
608
FEtype_error_string(string1);
573
if (type_of(string1) != t_base_string || type_of(string2) != t_base_string) {
574
output = compare_strings(string1, s1, e1, string2, s2, e2, 0, &e1);
611
577
output = compare_base(string1->base_string.self + s1, e1 - s1,
612
578
string2->base_string.self + s2, e2 - s2,
615
580
@(return ((output == 0)? Ct : Cnil))
646
611
get_string_start_end(string1, start1, end1, &s1, &e1);
647
612
get_string_start_end(string2, start2, end2, &s2, &e2);
648
613
#ifdef ECL_UNICODE
649
switch(type_of(string1)) {
651
switch(type_of(string2)) {
653
output = compare_extended(string1->string.self + s1, e1 - s1,
654
string2->string.self + s2, e2 - s2,
655
case_sensitive, &e1);
658
output = compare_mixed(string1->string.self + s1, e1 - s1,
659
string2->base_string.self + s2, e2 - s2,
660
case_sensitive, &e1);
664
switch(type_of(string2)) {
666
output = compare_mixed(string2->string.self + s2, e2 - s2,
667
string1->base_string.self + s1, e1 - s1,
668
case_sensitive, &e1);
672
output = compare_base(string1->base_string.self + s1, e1 - s1,
673
string2->base_string.self + s2, e2 - s2,
674
case_sensitive, &e1);
614
if (type_of(string1) != t_base_string || type_of(string2) != t_base_string) {
615
output = compare_strings(string1, s1, e1, string2, s2, e2,
616
case_sensitive, &e1);
620
output = compare_base(string1->base_string.self + s1, e1 - s1,
621
string2->base_string.self + s2, e2 - s2,
622
case_sensitive, &e1);
679
output = compare_base(string1->base_string.self + s1, e1 - s1,
680
string2->base_string.self + s2, e2 - s2,
681
case_sensitive, &e1);
683
625
if (output == sign1 || output == sign2) {
684
result = MAKE_FIXNUM(e1 + s1);
626
result = MAKE_FIXNUM(e1);
945
884
cl_parse_key(ARGS, 2, KEYS, KEY_VARS, NULL, FALSE);
947
assert_type_string(strng);
886
strng = ecl_check_type_string(fun,strng);
948
887
if (startp == Cnil) start = MAKE_FIXNUM(0);
949
888
get_string_start_end(strng, start, end, &s, &e);
951
switch(type_of(strng)) {
891
if (type_of(strng) == t_string) {
953
892
for (i = s; i < e; i++)
954
893
strng->string.self[i] = CODE_CHAR((*casefun)(CHAR_CODE(strng->string.self[i]), &b));
957
895
for (i = s; i < e; i++)
958
896
strng->base_string.self[i] = (*casefun)(strng->base_string.self[i], &b);
968
nstring_case(cl_narg narg, int (*casefun)(int, bool *), cl_va_list ARGS)
970
cl_object strng = cl_va_arg(ARGS);
974
#define start KEY_VARS[0]
975
#define end KEY_VARS[1]
976
#define startp KEY_VARS[2]
977
cl_object KEY_VARS[4];
979
if (narg < 1) FEwrong_num_arguments_anonym();
982
cl_parse_key(ARGS, 2, KEYS, KEY_VARS, NULL, FALSE);
984
assert_type_base_string(strng);
985
if (startp == Cnil) start = MAKE_FIXNUM(0);
986
get_string_start_end(strng, start, end, &s, &e);
988
899
for (i = s; i < e; i++)
989
900
strng->base_string.self[i] = (*casefun)(strng->base_string.self[i], &b);
997
908
@(defun nstring-upcase (&rest args)
999
return nstring_case(narg, char_upcase, args);
910
return nstring_case(narg, @'nstring-upcase', char_upcase, args);
1002
913
@(defun nstring-downcase (&rest args)
1004
return nstring_case(narg, char_downcase, args);
915
return nstring_case(narg, @'nstring-downcase', char_downcase, args);
1007
918
@(defun nstring-capitalize (&rest args)
1009
return nstring_case(narg, char_capitalize, args);
920
return nstring_case(narg, @'nstring-capitalize', char_capitalize, args);
1012
923
@(defun si::base_string_concatenate (&rest args)
1017
cl_object v, strings[narg];
1020
cl_object v, strings[NARG_MAX];
1024
if (narg > NARG_MAX)
1025
FEerror("si::string_concatenate: Too many arguments, limited to ~A", 1, MAKE_FIXNUM(NARG_MAX));
1027
/* FIXME! We should use cl_va_start() instead of this ugly trick */
1028
for (i = 0, l = 0; i < narg; i++) {
1029
strings[i] = si_coerce_to_base_string(cl_va_arg(args));
1030
l += strings[i]->base_string.fillp;
1032
v = cl_alloc_simple_base_string(l);
1033
for (i = 0, vself = v->base_string.self; i < narg; i++, vself += l) {
1034
l = strings[i]->base_string.fillp;
1035
memcpy(vself, strings[i]->base_string.self, l);
1041
@(defun si::extended_string_concatenate (&rest args)
1046
cl_object v, strings[narg];
1049
cl_object v, strings[NARG_MAX];
1053
if (narg > NARG_MAX)
1054
FEerror("si::string_concatenate: Too many arguments, limited to ~A", 1, MAKE_FIXNUM(NARG_MAX));
1056
/* FIXME! We should use cl_va_start() instead of this ugly trick */
1057
for (i = 0, l = 0; i < narg; i++) {
1058
strings[i] = si_coerce_to_extended_string(cl_va_arg(args));
1059
l += strings[i]->string.fillp;
1061
v = cl_alloc_simple_extended_string(l);
1062
for (i = 0, vself = v->string.self; i < narg; i++, vself += l) {
1063
l = strings[i]->string.fillp;
1064
memcpy(vself, strings[i]->string.self, l);
928
/* Compute final size and store NONEMPTY coerced strings. */
929
for (i = 0, l = 0; i < narg; i++) {
930
cl_object s = si_coerce_to_base_string(cl_va_arg(args));
931
if (s->base_string.fillp) {
933
l += s->base_string.fillp;
936
/* Do actual copying by recovering those strings */
937
output = cl_alloc_simple_base_string(l);
939
cl_object s = cl_stack_pop();
940
size_t bytes = s->base_string.fillp;
942
memcpy(output->base_string.self + l, s->base_string.self, bytes);
1072
948
ecl_string_push_extend(cl_object s, int c)
1074
cl_index new_length;
1076
951
switch(type_of(s)) {
1078
if (s->string.fillp >= s->string.dim) {
1080
if (!s->string.adjustable)
1081
FEerror("string-push-extend: the string ~S is not adjustable.",
1083
start_critical_section(); /* avoid losing p */
1084
if (s->string.dim >= ADIMLIM/2)
1085
FEerror("Can't extend the string.", 0);
1086
new_length = (s->string.dim + 1) * 2;
1087
p = (cl_object *)cl_alloc_align(sizeof (cl_object)*new_length, sizeof (cl_object));
1088
memcpy(p, s->string.self, s->string.dim * sizeof (cl_object));
1089
s->string.dim = new_length;
1090
adjust_displaced(s, p - s->string.self);
1091
end_critical_section();
1093
s->string.self[s->string.fillp++] = CODE_CHAR(c);
1095
955
case t_base_string:
956
/* We use the fact that both string types are
957
byte-compatible except for the data. */
1096
958
if (s->base_string.fillp >= s->base_string.dim) {
1098
961
if (!s->base_string.adjustable)
1099
962
FEerror("string-push-extend: the string ~S is not adjustable.",
1101
start_critical_section(); /* avoid losing p */
1102
if (s->base_string.dim >= ADIMLIM/2)
964
if (s->base_string.dim >= ADIMLIM)
1103
965
FEerror("Can't extend the string.", 0);
1104
new_length = (s->base_string.dim + 1) * 2;
1105
p = (char *)cl_alloc_atomic(new_length+1); p[new_length] = 0;
1106
memcpy(p, s->base_string.self, s->base_string.dim * sizeof(char));
1107
s->base_string.dim = new_length;
1108
adjust_displaced(s, p - (char *)s->base_string.self);
1109
end_critical_section();
966
new_length = 1 + s->base_string.dim + (s->base_string.dim / 2);
967
if (new_length > ADIMLIM)
968
new_length = ADIMLIM;
969
other = si_make_vector(cl_array_element_type(s),
970
MAKE_FIXNUM(new_length), Ct,
971
MAKE_FIXNUM(s->base_string.fillp),
972
Cnil, MAKE_FIXNUM(0));
973
ecl_copy_subarray(other, 0, s, 0, s->base_string.fillp);
974
s = si_replace_array(s, other);
1111
s->base_string.self[s->base_string.fillp++] = c;
976
ecl_char_set(s, s->base_string.fillp++, c);
1114
FEtype_error_string(s);
1119
ecl_string_push_extend(cl_object s, int c)
1122
cl_index new_length;
1124
if (type_of(s) != t_base_string) {
1125
FEtype_error_string(s);
1126
} else if (s->base_string.fillp >= s->base_string.dim) {
1127
if (!s->base_string.adjustable)
1128
FEerror("string-push-extend: the string ~S is not adjustable.",
1130
start_critical_section(); /* avoid losing p */
1131
if (s->base_string.dim >= ADIMLIM/2)
1132
FEerror("Can't extend the string.", 0);
1133
new_length = (s->base_string.dim + 1) * 2;
1134
p = (char *)cl_alloc_atomic(new_length+1); p[new_length] = 0;
1135
memcpy(p, s->base_string.self, s->base_string.dim * sizeof(char));
1136
s->base_string.dim = new_length;
1137
adjust_displaced(s, p - (char *)s->base_string.self);
1138
end_critical_section();
1140
s->base_string.self[s->base_string.fillp++] = c;
979
s = ecl_type_error(@'vector-push-extend',"",s,@'string');