KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > armedbear > lisp > StringFunctions


1 /*
2  * StringFunctions.java
3  *
4  * Copyright (C) 2003-2004 Peter Graves
5  * $Id: StringFunctions.java,v 1.28 2004/09/21 00:39:47 piso Exp $
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20  */

21
22 package org.armedbear.lisp;
23
24 public final class StringFunctions extends Lisp
25 {
26     // ### %string=
27
// Case sensitive.
28
private static final Primitive _STRING_EQUAL =
29         new Primitive("%string=", PACKAGE_SYS, false)
30     {
31         public LispObject execute(LispObject[] args) throws ConditionThrowable
32         {
33             if (args.length != 6)
34                 return signal(new WrongNumberOfArgumentsException(this));
35             char[] array1 = args[0].STRING().getStringChars();
36             char[] array2 = args[1].STRING().getStringChars();
37             int start1, end1, start2, end2;
38             try {
39                 start1 = ((Fixnum)args[2]).value;
40             }
41             catch (ClassCastException JavaDoc e) {
42                 return signal(new TypeError(args[2], Symbol.FIXNUM));
43             }
44             if (args[3] == NIL) {
45                 end1 = array1.length;
46             } else {
47                 try {
48                     end1 = ((Fixnum)args[3]).value;
49                 }
50                 catch (ClassCastException JavaDoc e) {
51                     return signal(new TypeError(args[3], Symbol.FIXNUM));
52                 }
53             }
54             try {
55                 start2 = ((Fixnum)args[4]).value;
56             }
57             catch (ClassCastException JavaDoc e) {
58                 return signal(new TypeError(args[4], Symbol.FIXNUM));
59             }
60             if (args[5] == NIL) {
61                 end2 = array2.length;
62             } else {
63                 try {
64                     end2 = ((Fixnum)args[5]).value;
65                 }
66                 catch (ClassCastException JavaDoc e) {
67                     return signal(new TypeError(args[5], Symbol.FIXNUM));
68                 }
69             }
70             if ((end1 - start1) != (end2 - start2))
71                 return NIL;
72             try {
73                 for (int i = start1, j = start2; i < end1; i++, j++) {
74                     if (array1[i] != array2[j])
75                         return NIL;
76                 }
77             }
78             catch (ArrayIndexOutOfBoundsException JavaDoc e) {
79                 // Shouldn't happen.
80
Debug.trace(e);
81                 return NIL;
82             }
83             return T;
84         }
85     };
86
87     // ### %%string=
88
// Case sensitive.
89
private static final Primitive2 __STRING_EQUAL =
90         new Primitive2("%%string=", PACKAGE_SYS, false)
91     {
92         public LispObject execute(LispObject first, LispObject second)
93             throws ConditionThrowable
94         {
95             char[] array1 = first.STRING().getStringChars();
96             char[] array2 = second.STRING().getStringChars();
97             if (array1.length != array2.length)
98                 return NIL;
99             for (int i = array1.length; i-- > 0;) {
100                 if (array1[i] != array2[i])
101                     return NIL;
102             }
103             return T;
104         }
105     };
106
107     // ### %string/=
108
// Case sensitive.
109
private static final Primitive _STRING_NOT_EQUAL =
110         new Primitive("%string/=", PACKAGE_SYS, true)
111     {
112         public LispObject execute(LispObject[] args) throws ConditionThrowable
113         {
114             if (args.length != 6)
115                 return signal(new WrongNumberOfArgumentsException(this));
116             char[] array1 = args[0].STRING().getStringChars();
117             char[] array2 = args[1].STRING().getStringChars();
118             int start1 = Fixnum.getInt(args[2]);
119             int end1 = Fixnum.getInt(args[3]);
120             int start2 = Fixnum.getInt(args[4]);
121             int end2 = Fixnum.getInt(args[5]);
122             int i = start1;
123             int j = start2;
124             while (true) {
125                 if (i == end1) {
126                     // Reached end of string1.
127
if (j == end2)
128                         return NIL; // Strings are identical.
129
return new Fixnum(i);
130                 }
131                 if (j == end2) {
132                     // Reached end of string2 before end of string1.
133
return new Fixnum(i);
134                 }
135                 if (array1[i] != array2[j])
136                     return new Fixnum(i);
137                 ++i;
138                 ++j;
139             }
140         }
141     };
142
143     // ### %string-equal
144
// Case insensitive.
145
private static final Primitive _STRING_EQUAL_IGNORE_CASE =
146         new Primitive("%string-equal", PACKAGE_SYS, true)
147     {
148         public LispObject execute(LispObject[] args) throws ConditionThrowable
149         {
150             if (args.length != 6)
151                 return signal(new WrongNumberOfArgumentsException(this));
152             char[] array1 = args[0].STRING().getStringChars();
153             char[] array2 = args[1].STRING().getStringChars();
154             int start1 = Fixnum.getInt(args[2]);
155             int end1 = Fixnum.getInt(args[3]);
156             int start2 = Fixnum.getInt(args[4]);
157             int end2 = Fixnum.getInt(args[5]);
158             if ((end1 - start1) != (end2 - start2))
159                 return NIL;
160             int i, j;
161             for (i = start1, j = start2; i < end1; i++, j++) {
162                 char c1 = array1[i];
163                 char c2 = array2[j];
164                 if (c1 == c2)
165                     continue;
166                 if (Utilities.toUpperCase(c1) == Utilities.toUpperCase(c2))
167                     continue;
168                 if (Utilities.toLowerCase(c1) == Utilities.toLowerCase(c2))
169                     continue;
170                 return NIL;
171             }
172             return T;
173         }
174     };
175
176     // ### %string-not-equal
177
// Case sensitive.
178
private static final Primitive _STRING_NOT_EQUAL_IGNORE_CASE =
179         new Primitive("%string-not-equal", PACKAGE_SYS, true)
180     {
181         public LispObject execute(LispObject[] args) throws ConditionThrowable
182         {
183             if (args.length != 6)
184                 return signal(new WrongNumberOfArgumentsException(this));
185             char[] array1 = args[0].STRING().getStringChars();
186             char[] array2 = args[1].STRING().getStringChars();
187             int start1 = Fixnum.getInt(args[2]);
188             int end1 = Fixnum.getInt(args[3]);
189             int start2 = Fixnum.getInt(args[4]);
190             int end2 = Fixnum.getInt(args[5]);
191             int i = start1;
192             int j = start2;
193             while (true) {
194                 if (i == end1) {
195                     // Reached end of string1.
196
if (j == end2)
197                         return NIL; // Strings are identical.
198
return new Fixnum(i);
199                 }
200                 if (j == end2) {
201                     // Reached end of string2.
202
return new Fixnum(i);
203                 }
204                 char c1 = array1[i];
205                 char c2 = array2[j];
206                 if (c1 == c2 ||
207                     Utilities.toUpperCase(c1) == Utilities.toUpperCase(c2) ||
208                     Utilities.toLowerCase(c1) == Utilities.toLowerCase(c2))
209                 {
210                     ++i;
211                     ++j;
212                     continue;
213                 }
214                 return new Fixnum(i);
215             }
216         }
217     };
218
219     // ### %string<
220
// Case sensitive.
221
private static final Primitive _STRING_LESS_THAN =
222         new Primitive("%string<", PACKAGE_SYS, true)
223     {
224         public LispObject execute(LispObject[] args) throws ConditionThrowable
225         {
226             if (args.length != 6)
227                 return signal(new WrongNumberOfArgumentsException(this));
228             char[] array1 = args[0].STRING().getStringChars();
229             char[] array2 = args[1].STRING().getStringChars();
230             int start1 = Fixnum.getInt(args[2]);
231             int end1 = Fixnum.getInt(args[3]);
232             int start2 = Fixnum.getInt(args[4]);
233             int end2 = Fixnum.getInt(args[5]);
234             int i = start1;
235             int j = start2;
236             while (true) {
237                 if (i == end1) {
238                     // Reached end of string1.
239
if (j == end2)
240                         return NIL; // Strings are identical.
241
return new Fixnum(i);
242                 }
243                 if (j == end2) {
244                     // Reached end of string2.
245
return NIL;
246                 }
247                 char c1 = array1[i];
248                 char c2 = array2[j];
249                 if (c1 == c2) {
250                     ++i;
251                     ++j;
252                     continue;
253                 }
254                 if (c1 < c2)
255                     return new Fixnum(i);
256                 // c1 > c2
257
return NIL;
258             }
259         }
260     };
261
262     // ### %string<=
263
// Case sensitive.
264
private static final Primitive _STRING_GREATER_THAN =
265         new Primitive("%string>", PACKAGE_SYS, true)
266     {
267         public LispObject execute(LispObject[] args) throws ConditionThrowable
268         {
269             if (args.length != 6)
270                 return signal(new WrongNumberOfArgumentsException(this));
271             char[] array1 = args[0].STRING().getStringChars();
272             char[] array2 = args[1].STRING().getStringChars();
273             int start1 = Fixnum.getInt(args[2]);
274             int end1 = Fixnum.getInt(args[3]);
275             int start2 = Fixnum.getInt(args[4]);
276             int end2 = Fixnum.getInt(args[5]);
277             int i = start1;
278             int j = start2;
279             while (true) {
280                 if (i == end1) {
281                     // Reached end of string1.
282
return NIL;
283                 }
284                 if (j == end2) {
285                     // Reached end of string2.
286
return new Fixnum(i);
287                 }
288                 char c1 = array1[i];
289                 char c2 = array2[j];
290                 if (c1 == c2) {
291                     ++i;
292                     ++j;
293                     continue;
294                 }
295                 if (c1 < c2)
296                     return NIL;
297                 // c1 > c2
298
return new Fixnum(i);
299             }
300         }
301     };
302
303     // ### %string<=
304
// Case sensitive.
305
private static final Primitive _STRING_LE =
306         new Primitive("%string<=", PACKAGE_SYS, true)
307     {
308         public LispObject execute(LispObject[] args) throws ConditionThrowable
309         {
310             if (args.length != 6)
311                 return signal(new WrongNumberOfArgumentsException(this));
312             char[] array1 = args[0].STRING().getStringChars();
313             char[] array2 = args[1].STRING().getStringChars();
314             int start1 = Fixnum.getInt(args[2]);
315             int end1 = Fixnum.getInt(args[3]);
316             int start2 = Fixnum.getInt(args[4]);
317             int end2 = Fixnum.getInt(args[5]);
318             int i = start1;
319             int j = start2;
320             while (true) {
321                 if (i == end1) {
322                     // Reached end of string1.
323
return new Fixnum(i);
324                 }
325                 if (j == end2) {
326                     // Reached end of string2.
327
return NIL;
328                 }
329                 char c1 = array1[i];
330                 char c2 = array2[j];
331                 if (c1 == c2) {
332                     ++i;
333                     ++j;
334                     continue;
335                 }
336                 if (c1 > c2)
337                     return NIL;
338                 // c1 < c2
339
return new Fixnum(i);
340             }
341         }
342     };
343
344     // ### %string<=
345
// Case sensitive.
346
private static final Primitive _STRING_GE =
347         new Primitive("%string>=", PACKAGE_SYS, true)
348     {
349         public LispObject execute(LispObject[] args) throws ConditionThrowable
350         {
351             if (args.length != 6)
352                 return signal(new WrongNumberOfArgumentsException(this));
353             char[] array1 = args[0].STRING().getStringChars();
354             char[] array2 = args[1].STRING().getStringChars();
355             int start1 = Fixnum.getInt(args[2]);
356             int end1 = Fixnum.getInt(args[3]);
357             int start2 = Fixnum.getInt(args[4]);
358             int end2 = Fixnum.getInt(args[5]);
359             int i = start1;
360             int j = start2;
361             while (true) {
362                 if (i == end1) {
363                     // Reached end of string1.
364
if (j == end2)
365                         return new Fixnum(i); // Strings are identical.
366
return NIL;
367                 }
368                 if (j == end2) {
369                     // Reached end of string2.
370
return new Fixnum(i);
371                 }
372                 char c1 = array1[i];
373                 char c2 = array2[j];
374                 if (c1 == c2) {
375                     ++i;
376                     ++j;
377                     continue;
378                 }
379                 if (c1 < c2)
380                     return NIL;
381                 // c1 > c2
382
return new Fixnum(i);
383             }
384         }
385     };
386
387     // ### %string-lessp
388
// Case insensitive.
389
private static final Primitive _STRING_LESSP =
390         new Primitive("%string-lessp", PACKAGE_SYS, true)
391     {
392         public LispObject execute(LispObject[] args) throws ConditionThrowable
393         {
394             if (args.length != 6)
395                 return signal(new WrongNumberOfArgumentsException(this));
396             char[] array1 = args[0].STRING().getStringChars();
397             char[] array2 = args[1].STRING().getStringChars();
398             int start1 = Fixnum.getInt(args[2]);
399             int end1 = Fixnum.getInt(args[3]);
400             int start2 = Fixnum.getInt(args[4]);
401             int end2 = Fixnum.getInt(args[5]);
402             int i = start1;
403             int j = start2;
404             while (true) {
405                 if (i == end1) {
406                     // Reached end of string1.
407
if (j == end2)
408                         return NIL; // Strings are identical.
409
return new Fixnum(i);
410                 }
411                 if (j == end2) {
412                     // Reached end of string2.
413
return NIL;
414                 }
415                 char c1 = Utilities.toUpperCase(array1[i]);
416                 char c2 = Utilities.toUpperCase(array2[j]);
417                 if (c1 == c2) {
418                     ++i;
419                     ++j;
420                     continue;
421                 }
422                 if (c1 > c2)
423                     return NIL;
424                 // c1 < c2
425
return new Fixnum(i);
426             }
427         }
428     };
429
430     // ### %string-greaterp
431
// Case insensitive.
432
private static final Primitive _STRING_GREATERP =
433         new Primitive("%string-greaterp", PACKAGE_SYS, true)
434     {
435         public LispObject execute(LispObject[] args) throws ConditionThrowable
436         {
437             if (args.length != 6)
438                 return signal(new WrongNumberOfArgumentsException(this));
439             char[] array1 = args[0].STRING().getStringChars();
440             char[] array2 = args[1].STRING().getStringChars();
441             int start1 = Fixnum.getInt(args[2]);
442             int end1 = Fixnum.getInt(args[3]);
443             int start2 = Fixnum.getInt(args[4]);
444             int end2 = Fixnum.getInt(args[5]);
445             int i = start1;
446             int j = start2;
447             while (true) {
448                 if (i == end1) {
449                     // Reached end of string1.
450
return NIL;
451                 }
452                 if (j == end2) {
453                     // Reached end of string2.
454
return new Fixnum(i);
455                 }
456                 char c1 = Utilities.toUpperCase(array1[i]);
457                 char c2 = Utilities.toUpperCase(array2[j]);
458                 if (c1 == c2) {
459                     ++i;
460                     ++j;
461                     continue;
462                 }
463                 if (c1 < c2)
464                     return NIL;
465                 // c1 > c2
466
return new Fixnum(i);
467             }
468         }
469     };
470
471     // ### %string-not-lessp
472
// Case insensitive.
473
private static final Primitive _STRING_NOT_LESSP =
474         new Primitive("%string-not-lessp", PACKAGE_SYS, true)
475     {
476         public LispObject execute(LispObject[] args) throws ConditionThrowable
477         {
478             if (args.length != 6)
479                 return signal(new WrongNumberOfArgumentsException(this));
480             char[] array1 = args[0].STRING().getStringChars();
481             char[] array2 = args[1].STRING().getStringChars();
482             int start1 = Fixnum.getInt(args[2]);
483             int end1 = Fixnum.getInt(args[3]);
484             int start2 = Fixnum.getInt(args[4]);
485             int end2 = Fixnum.getInt(args[5]);
486             int i = start1;
487             int j = start2;
488             while (true) {
489                 if (i == end1) {
490                     // Reached end of string1.
491
if (j == end2)
492                         return new Fixnum(i); // Strings are identical.
493
return NIL;
494                 }
495                 if (j == end2) {
496                     // Reached end of string2.
497
return new Fixnum(i);
498                 }
499                 char c1 = Utilities.toUpperCase(array1[i]);
500                 char c2 = Utilities.toUpperCase(array2[j]);
501                 if (c1 == c2) {
502                     ++i;
503                     ++j;
504                     continue;
505                 }
506                 if (c1 > c2)
507                     return new Fixnum(i);
508                 // c1 < c2
509
return NIL;
510             }
511         }
512     };
513
514     // ### %string-not-greaterp
515
// Case insensitive.
516
private static final Primitive _STRING_NOT_GREATERP =
517         new Primitive("%string-not-greaterp", PACKAGE_SYS, true)
518     {
519         public LispObject execute(LispObject[] args) throws ConditionThrowable
520         {
521             if (args.length != 6)
522                 return signal(new WrongNumberOfArgumentsException(this));
523             char[] array1 = args[0].STRING().getStringChars();
524             char[] array2 = args[1].STRING().getStringChars();
525             int start1 = Fixnum.getInt(args[2]);
526             int end1 = Fixnum.getInt(args[3]);
527             int start2 = Fixnum.getInt(args[4]);
528             int end2 = Fixnum.getInt(args[5]);
529             int i = start1;
530             int j = start2;
531             while (true) {
532                 if (i == end1) {
533                     // Reached end of string1.
534
return new Fixnum(i);
535                 }
536                 if (j == end2) {
537                     // Reached end of string2.
538
return NIL;
539                 }
540                 char c1 = Utilities.toUpperCase(array1[i]);
541                 char c2 = Utilities.toUpperCase(array2[j]);
542                 if (c1 == c2) {
543                     ++i;
544                     ++j;
545                     continue;
546                 }
547                 if (c1 > c2)
548                     return NIL;
549                 // c1 < c2
550
return new Fixnum(i);
551             }
552         }
553     };
554
555     // ### %string-upcase
556
private static final Primitive3 _STRING_UPCASE =
557         new Primitive3("%string-upcase", PACKAGE_SYS, true)
558     {
559         public LispObject execute(LispObject first, LispObject second,
560             LispObject third) throws ConditionThrowable
561         {
562             LispObject s = first.STRING();
563             final int length = s.length();
564             int start = (int) Fixnum.getValue(second);
565             if (start < 0 || start > length)
566                 return signal(new TypeError("Invalid start position " + start + "."));
567             int end;
568             if (third == NIL)
569                 end = length;
570             else
571                 end = (int) Fixnum.getValue(third);
572             if (end < 0 || end > length)
573                 return signal(new TypeError("Invalid end position " + start + "."));
574             if (start > end)
575                 return signal(new TypeError("Start (" + start + ") is greater than end (" + end + ")."));
576             StringBuffer JavaDoc sb = new StringBuffer JavaDoc(length);
577             char[] array = s.getStringChars();
578             int i;
579             for (i = 0; i < start; i++)
580                 sb.append(array[i]);
581             for (i = start; i < end; i++)
582                 sb.append(Utilities.toUpperCase(array[i]));
583             for (i = end; i < length; i++)
584                 sb.append(array[i]);
585             return new SimpleString(sb);
586         }
587     };
588
589     // ### %string-downcase
590
private static final Primitive3 _STRING_DOWNCASE =
591         new Primitive3("%string-downcase", PACKAGE_SYS, true)
592     {
593         public LispObject execute(LispObject first, LispObject second,
594             LispObject third) throws ConditionThrowable
595         {
596             LispObject s = first.STRING();
597             final int length = s.length();
598             int start = (int) Fixnum.getValue(second);
599             if (start < 0 || start > length)
600                 return signal(new TypeError("Invalid start position " + start + "."));
601             int end;
602             if (third == NIL)
603                 end = length;
604             else
605                 end = (int) Fixnum.getValue(third);
606             if (end < 0 || end > length)
607                 return signal(new TypeError("Invalid end position " + start + "."));
608             if (start > end)
609                 return signal(new TypeError("Start (" + start + ") is greater than end (" + end + ")."));
610             StringBuffer JavaDoc sb = new StringBuffer JavaDoc(length);
611             char[] array = s.getStringChars();
612             int i;
613             for (i = 0; i < start; i++)
614                 sb.append(array[i]);
615             for (i = start; i < end; i++)
616                 sb.append(Utilities.toLowerCase(array[i]));
617             for (i = end; i < length; i++)
618                 sb.append(array[i]);
619             return new SimpleString(sb);
620         }
621     };
622
623     // ### %string-capitalize
624
private static final Primitive3 _STRING_CAPITALIZE=
625         new Primitive3("%string-capitalize", PACKAGE_SYS, true)
626     {
627         public LispObject execute(LispObject first, LispObject second,
628             LispObject third) throws ConditionThrowable
629         {
630             LispObject s = first.STRING();
631             final int length = s.length();
632             int start = (int) Fixnum.getValue(second);
633             if (start < 0 || start > length)
634                 return signal(new TypeError("Invalid start position " + start + "."));
635             int end;
636             if (third == NIL)
637                 end = length;
638             else
639                 end = (int) Fixnum.getValue(third);
640             if (end < 0 || end > length)
641                 return signal(new TypeError("Invalid end position " + start + "."));
642             if (start > end)
643                 return signal(new TypeError("Start (" + start + ") is greater than end (" + end + ")."));
644             StringBuffer JavaDoc sb = new StringBuffer JavaDoc(length);
645             char[] array = s.getStringChars();
646             boolean lastCharWasAlphanumeric = false;
647             int i;
648             for (i = 0; i < start; i++)
649                 sb.append(array[i]);
650             for (i = start; i < end; i++) {
651                 char c = array[i];
652                 if (Character.isLowerCase(c)) {
653                     sb.append(lastCharWasAlphanumeric ? c : Utilities.toUpperCase(c));
654                     lastCharWasAlphanumeric = true;
655                 } else if (Character.isUpperCase(c)) {
656                     sb.append(lastCharWasAlphanumeric ? Utilities.toLowerCase(c) : c);
657                     lastCharWasAlphanumeric = true;
658                 } else {
659                     sb.append(c);
660                     lastCharWasAlphanumeric = Character.isDigit(c);
661                 }
662             }
663             for (i = end; i < length; i++)
664                 sb.append(array[i]);
665             return new SimpleString(sb);
666         }
667     };
668
669     // ### %nstring-upcase
670
private static final Primitive3 _NSTRING_UPCASE =
671         new Primitive3("%nstring-upcase", PACKAGE_SYS, true)
672     {
673         public LispObject execute(LispObject first, LispObject second,
674             LispObject third) throws ConditionThrowable
675         {
676             AbstractString string;
677             try {
678                 string = (AbstractString) first;
679             }
680             catch (ClassCastException JavaDoc e) {
681                 return signal(new TypeError(first, Symbol.STRING));
682             }
683             final int length = string.length();
684             int start = (int) Fixnum.getValue(second);
685             if (start < 0 || start > length)
686                 return signal(new TypeError("Invalid start position " + start + "."));
687             int end;
688             if (third == NIL)
689                 end = length;
690             else
691                 end = (int) Fixnum.getValue(third);
692             if (end < 0 || end > length)
693                 return signal(new TypeError("Invalid end position " + start + "."));
694             if (start > end)
695                 return signal(new TypeError("Start (" + start + ") is greater than end (" + end + ")."));
696             for (int i = start; i < end; i++)
697                 string.setChar(i, Utilities.toUpperCase(string.getChar(i)));
698             return string;
699         }
700     };
701
702     // ### %nstring-downcase
703
private static final Primitive3 _NSTRING_DOWNCASE =
704         new Primitive3("%nstring-downcase", PACKAGE_SYS, true)
705     {
706         public LispObject execute(LispObject first, LispObject second,
707             LispObject third) throws ConditionThrowable
708         {
709             AbstractString string;
710             try {
711                 string = (AbstractString) first;
712             }
713             catch (ClassCastException JavaDoc e) {
714                 return signal(new TypeError(first, Symbol.STRING));
715             }
716             final int length = string.length();
717             int start = (int) Fixnum.getValue(second);
718             if (start < 0 || start > length)
719                 return signal(new TypeError("Invalid start position " + start + "."));
720             int end;
721             if (third == NIL)
722                 end = length;
723             else
724                 end = (int) Fixnum.getValue(third);
725             if (end < 0 || end > length)
726                 return signal(new TypeError("Invalid end position " + start + "."));
727             if (start > end)
728                 return signal(new TypeError("Start (" + start + ") is greater than end (" + end + ")."));
729             for (int i = start; i < end; i++)
730                 string.setChar(i, Utilities.toLowerCase(string.getChar(i)));
731             return string;
732         }
733     };
734
735     // ### %nstring-capitalize
736
private static final Primitive3 _NSTRING_CAPITALIZE =
737         new Primitive3("%nstring-capitalize", PACKAGE_SYS, true)
738     {
739         public LispObject execute(LispObject first, LispObject second,
740             LispObject third) throws ConditionThrowable
741         {
742             AbstractString string;
743             try {
744                 string = (AbstractString) first;
745             }
746             catch (ClassCastException JavaDoc e) {
747                 return signal(new TypeError(first, Symbol.STRING));
748             }
749             final int length = string.length();
750             int start = (int) Fixnum.getValue(second);
751             if (start < 0 || start > length)
752                 return signal(new TypeError("Invalid start position " + start + "."));
753             int end;
754             if (third == NIL)
755                 end = length;
756             else
757                 end = (int) Fixnum.getValue(third);
758             if (end < 0 || end > length)
759                 return signal(new TypeError("Invalid end position " + start + "."));
760             if (start > end)
761                 return signal(new TypeError("Start (" + start + ") is greater than end (" + end + ")."));
762             boolean lastCharWasAlphanumeric = false;
763             for (int i = start; i < end; i++) {
764                 char c = string.getChar(i);
765                 if (Character.isLowerCase(c)) {
766                     if (!lastCharWasAlphanumeric)
767                         string.setChar(i, Utilities.toUpperCase(c));
768                     lastCharWasAlphanumeric = true;
769                 } else if (Character.isUpperCase(c)) {
770                     if (lastCharWasAlphanumeric)
771                         string.setChar(i, Utilities.toLowerCase(c));
772                     lastCharWasAlphanumeric = true;
773                 } else
774                     lastCharWasAlphanumeric = Character.isDigit(c);
775             }
776             return string;
777         }
778     };
779
780     // ### stringp
781
public static final Primitive1 STRINGP = new Primitive1("stringp", "object")
782     {
783         public LispObject execute(LispObject arg) throws ConditionThrowable
784         {
785             return arg.STRINGP();
786         }
787     };
788
789     // ### simple-string-p
790
public static final Primitive1 SIMPLE_STRING_P =
791         new Primitive1("simple-string-p", "object")
792     {
793         public LispObject execute(LispObject arg) throws ConditionThrowable
794         {
795             return arg.SIMPLE_STRING_P();
796         }
797     };
798
799     // ### %make-string
800
// %make-string size initial-element element-type => string
801
// Returns a simple string.
802
private static final Primitive3 _MAKE_STRING =
803         new Primitive3("%make-string", PACKAGE_SYS, false)
804     {
805         public LispObject execute(LispObject size, LispObject initialElement,
806                                   LispObject elementType)
807             throws ConditionThrowable
808         {
809             final int n;
810             try {
811                 n = ((Fixnum)size).value;
812             }
813             catch (ClassCastException JavaDoc e) {
814                 return signal(new TypeError(size, Symbol.FIXNUM));
815             }
816             if (n < 0 || n >= ARRAY_DIMENSION_MAX) {
817                 StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
818                 sb.append("The size specified for this string (");
819                 sb.append(n);
820                 sb.append(')');
821                 if (n >= ARRAY_DIMENSION_MAX) {
822                     sb.append(" is >= ARRAY-DIMENSION-LIMIT (");
823                     sb.append(ARRAY_DIMENSION_MAX);
824                     sb.append(").");
825                 } else
826                     sb.append(" is negative.");
827                 return signal(new LispError(sb.toString()));
828             }
829             // Ignore elementType.
830
SimpleString string = new SimpleString(n);
831             if (initialElement != NIL) {
832                 // Initial element was specified.
833
char c = checkCharacter(initialElement).getValue();
834                 string.fill(c);
835             }
836             return string;
837         }
838     };
839
840     // ### char
841
private static final Primitive2 CHAR = new Primitive2("char", "string index")
842     {
843         public LispObject execute(LispObject first, LispObject second)
844             throws ConditionThrowable
845         {
846             try {
847                 return ((AbstractString)first).getRowMajor(((Fixnum)second).value);
848             }
849             catch (ClassCastException JavaDoc e) {
850                 if (first instanceof AbstractString)
851                     return signal(new TypeError(second, Symbol.FIXNUM));
852                 else
853                     return signal(new TypeError(first, Symbol.STRING));
854             }
855         }
856     };
857
858     // ### %set-char
859
private static final Primitive3 _SET_CHAR =
860         new Primitive3("%set-char", PACKAGE_SYS, false)
861     {
862         public LispObject execute(LispObject first, LispObject second,
863                                   LispObject third)
864             throws ConditionThrowable
865         {
866             try {
867                 ((AbstractString)first).setRowMajor(((Fixnum)second).value,
868                                                     ((LispCharacter)third));
869                 return third;
870             }
871             catch (ClassCastException JavaDoc e) {
872                 if (!(first instanceof AbstractString))
873                     return signal(new TypeError(first, Symbol.STRING));
874                 else if (!(second instanceof Fixnum))
875                     return signal(new TypeError(second, Symbol.FIXNUM));
876                 else
877                     return signal(new TypeError(third, Symbol.CHARACTER));
878             }
879         }
880     };
881
882     // ### string-position
883
private static final Primitive3 STRING_POSITION =
884         new Primitive3("string-position", PACKAGE_EXT, true)
885     {
886         public LispObject execute(LispObject first, LispObject second,
887                                   LispObject third)
888             throws ConditionThrowable
889         {
890             char c = LispCharacter.getValue(first);
891             AbstractString string;
892             if (second instanceof AbstractString)
893                 string = (AbstractString) second;
894             else
895                 return signal(new TypeError(second, Symbol.STRING));
896             int start = Fixnum.getValue(third);
897             for (int i = start, limit = string.length(); i < limit; i++) {
898                 if (string.getChar(i) == c)
899                     return number(i);
900             }
901             return NIL;
902         }
903     };
904
905     // ### simple-string-search pattern string => position
906
// Searches string for a substring that matches pattern.
907
private static final Primitive2 SIMPLE_STRING_SEARCH =
908         new Primitive2("simple-string-search", PACKAGE_EXT, true)
909     {
910         public LispObject execute(LispObject first, LispObject second)
911             throws ConditionThrowable
912         {
913             // FIXME Don't call getStringValue() here! (Just look at the chars.)
914
int index = second.getStringValue().indexOf(first.getStringValue());
915             return index >= 0 ? new Fixnum(index) : NIL;
916         }
917     };
918
919     // ### simple-string-fill string character => string
920
private static final Primitive2 STRING_FILL =
921         new Primitive2("simple-string-fill", PACKAGE_EXT, true)
922     {
923         public LispObject execute(LispObject first, LispObject second)
924             throws ConditionThrowable
925         {
926             try {
927                 AbstractString s = (AbstractString) first;
928                 s.fill(LispCharacter.getValue(second));
929                 return first;
930             }
931             catch (ClassCastException JavaDoc e) {
932                 return signal(new TypeError(first, Symbol.SIMPLE_STRING));
933             }
934         }
935     };
936 }
937
Popular Tags