[armedbear-cvs] r12488 - trunk/abcl/src/org/armedbear/lisp
Ville Voutilainen
vvoutilainen at common-lisp.net
Sat Feb 20 17:28:55 UTC 2010
Author: vvoutilainen
Date: Sat Feb 20 12:28:52 2010
New Revision: 12488
Log:
1) remove copy-paste code, consolidate index and char array extraction
2) make string= use Arrays.equals
3) implement index-version of string= in terms of string/=
4) implement string-equal in terms of string-not-equal
5) implement string> in terms of string<
6) implement string>= in terms of string<=
The work will continue by doing string-lessp and string-greaterp
in terms of one of them, same for string-not-lessp and string-not-greterp
and so on. Thanks to Alessio Stalla for explaining how the various
indices work.
Modified:
trunk/abcl/src/org/armedbear/lisp/StringFunctions.java
Modified: trunk/abcl/src/org/armedbear/lisp/StringFunctions.java
==============================================================================
--- trunk/abcl/src/org/armedbear/lisp/StringFunctions.java (original)
+++ trunk/abcl/src/org/armedbear/lisp/StringFunctions.java Sat Feb 20 12:28:52 2010
@@ -34,8 +34,41 @@
package org.armedbear.lisp;
import static org.armedbear.lisp.Lisp.*;
-
+import java.util.Arrays;
public final class StringFunctions {
+ private final static class StringIndicesAndChars {
+
+ public char[] array1;
+ public char[] array2;
+ public int start1 = 0;
+ public int end1;
+ public int start2 = 0;
+ public int end2;
+ };
+ private final static StringIndicesAndChars
+ stringIndicesAndChars(LispObject... params) {
+ StringIndicesAndChars retVal = new StringIndicesAndChars();
+ retVal.array1 = params[0].STRING().getStringChars();
+ retVal.array2 = params[1].STRING().getStringChars();
+ retVal.end1 = retVal.array1.length;
+ retVal.end2 = retVal.array2.length;
+ if (params.length > 2) {
+ if (params[2] != NIL) {
+ retVal.start1 = Fixnum.getValue(params[2]);
+ }
+ if (params[3] != NIL) {
+ retVal.end1 = Fixnum.getValue(params[3]);
+ }
+ if (params[4] != NIL) {
+ retVal.start2 = Fixnum.getValue(params[4]);
+ }
+ if (params[5] != NIL) {
+ retVal.end2 = Fixnum.getValue(params[5]);
+ }
+ }
+ return retVal;
+ }
+
// ### %string=
// Case sensitive.
private static final Primitive _STRING_EQUAL = new pf__string_equal();
@@ -50,34 +83,10 @@
LispObject fifth, LispObject sixth)
{
- char[] array1 = first.STRING().getStringChars();
- char[] array2 = second.STRING().getStringChars();
- int start1, end1, start2, end2;
- start1 = Fixnum.getValue(third);
- if (fourth == NIL) {
- end1 = array1.length;
- } else {
- end1 = Fixnum.getValue(fourth);
- }
- start2 = Fixnum.getValue(fifth);
- if (sixth == NIL) {
- end2 = array2.length;
- } else {
- end2 = Fixnum.getValue(sixth);
- }
- if ((end1 - start1) != (end2 - start2))
- return NIL;
- try {
- for (int i = start1, j = start2; i < end1; i++, j++) {
- if (array1[i] != array2[j])
- return NIL;
- }
- } catch (ArrayIndexOutOfBoundsException e) {
- // Shouldn't happen.
- Debug.trace(e);
- return NIL;
- }
- return T;
+ return
+ (_STRING_NOT_EQUAL.execute(first, second, third,
+ fourth, fifth, sixth)
+ == NIL) ? T : NIL;
}
};
@@ -93,17 +102,11 @@
public LispObject execute(LispObject first, LispObject second)
{
- char[] array1 = first.STRING().getStringChars();
- char[] array2 = second.STRING().getStringChars();
- if (array1.length != array2.length)
- return NIL;
- for (int i = array1.length; i-- > 0;) {
- if (array1[i] != array2[i])
- return NIL;
- }
- return T;
- }
- };
+ StringIndicesAndChars chars = stringIndicesAndChars(first, second);
+ return Arrays.equals(chars.array1, chars.array2) ?
+ T : NIL;
+ };
+ }
// ### %string/=
// Case sensitive.
@@ -114,29 +117,26 @@
}
@Override
- public LispObject execute(LispObject[] args) {
- if (args.length != 6)
- return error(new WrongNumberOfArgumentsException(this));
- char[] array1 = args[0].STRING().getStringChars();
- char[] array2 = args[1].STRING().getStringChars();
- int start1 = Fixnum.getValue(args[2]);
- int end1 = Fixnum.getValue(args[3]);
- int start2 = Fixnum.getValue(args[4]);
- int end2 = Fixnum.getValue(args[5]);
- int i = start1;
- int j = start2;
+ public LispObject execute(LispObject first, LispObject second,
+ LispObject third, LispObject fourth,
+ LispObject fifth, LispObject sixth) {
+ StringIndicesAndChars indicesAndChars =
+ stringIndicesAndChars(first, second, third, fourth,
+ fifth, sixth);
+ int i = indicesAndChars.start1;
+ int j = indicesAndChars.start2;
while (true) {
- if (i == end1) {
+ if (i == indicesAndChars.end1) {
// Reached end of string1.
- if (j == end2)
+ if (j == indicesAndChars.end2)
return NIL; // Strings are identical.
return Fixnum.getInstance(i);
}
- if (j == end2) {
+ if (j == indicesAndChars.end2) {
// Reached end of string2 before end of string1.
return Fixnum.getInstance(i);
}
- if (array1[i] != array2[j])
+ if (indicesAndChars.array1[i] != indicesAndChars.array2[j])
return Fixnum.getInstance(i);
++i;
++j;
@@ -158,32 +158,14 @@
LispObject fifth, LispObject sixth)
{
- char[] array1 = first.STRING().getStringChars();
- char[] array2 = second.STRING().getStringChars();
- int start1 = Fixnum.getValue(third);
- int end1 = Fixnum.getValue(fourth);
- int start2 = Fixnum.getValue(fifth);
- int end2 = Fixnum.getValue(sixth);
- if ((end1 - start1) != (end2 - start2))
- return NIL;
- int i, j;
- for (i = start1, j = start2; i < end1; i++, j++) {
- char c1 = array1[i];
- char c2 = array2[j];
- if (c1 == c2)
- continue;
- if (LispCharacter.toUpperCase(c1) == LispCharacter.toUpperCase(c2))
- continue;
- if (LispCharacter.toLowerCase(c1) == LispCharacter.toLowerCase(c2))
- continue;
- return NIL;
- }
- return T;
+ return (_STRING_NOT_EQUAL_IGNORE_CASE.execute(first, second, third,
+ fourth, fifth, sixth)
+ == NIL) ? T : NIL;
}
};
// ### %string-not-equal
- // Case sensitive.
+ // Case insensitive.
private static final Primitive _STRING_NOT_EQUAL_IGNORE_CASE = new pf__string_not_equal_ignore_case();
private static final class pf__string_not_equal_ignore_case extends Primitive {
pf__string_not_equal_ignore_case() {
@@ -191,30 +173,27 @@
}
@Override
- public LispObject execute(LispObject[] args) {
- if (args.length != 6)
- return error(new WrongNumberOfArgumentsException(this));
- char[] array1 = args[0].STRING().getStringChars();
- char[] array2 = args[1].STRING().getStringChars();
- int start1 = Fixnum.getValue(args[2]);
- int end1 = Fixnum.getValue(args[3]);
- int start2 = Fixnum.getValue(args[4]);
- int end2 = Fixnum.getValue(args[5]);
- int i = start1;
- int j = start2;
+ public LispObject execute(LispObject first, LispObject second,
+ LispObject third, LispObject fourth,
+ LispObject fifth, LispObject sixth) {
+ StringIndicesAndChars indicesAndChars =
+ stringIndicesAndChars(first, second, third, fourth,
+ fifth, sixth);
+ int i = indicesAndChars.start1;
+ int j = indicesAndChars.start2;
while (true) {
- if (i == end1) {
+ if (i == indicesAndChars.end1) {
// Reached end of string1.
- if (j == end2)
+ if (j == indicesAndChars.end2)
return NIL; // Strings are identical.
return Fixnum.getInstance(i);
}
- if (j == end2) {
+ if (j == indicesAndChars.end2) {
// Reached end of string2.
return Fixnum.getInstance(i);
}
- char c1 = array1[i];
- char c2 = array2[j];
+ char c1 = indicesAndChars.array1[i];
+ char c2 = indicesAndChars.array2[j];
if (c1 == c2 ||
LispCharacter.toUpperCase(c1) == LispCharacter.toUpperCase(c2) ||
LispCharacter.toLowerCase(c1) == LispCharacter.toLowerCase(c2)) {
@@ -229,6 +208,33 @@
// ### %string<
// Case sensitive.
+ private static int lessThan(StringIndicesAndChars indicesAndChars) {
+ int i = indicesAndChars.start1;
+ int j = indicesAndChars.start2;
+ while (true) {
+ if (i == indicesAndChars.end1) {
+ // Reached end of string1.
+ if (j == indicesAndChars.end2)
+ return -1; // Strings are identical.
+ return i;
+ }
+ if (j == indicesAndChars.end2) {
+ // Reached end of string2.
+ return -1;
+ }
+ char c1 = indicesAndChars.array1[i];
+ char c2 = indicesAndChars.array2[j];
+ if (c1 == c2) {
+ ++i;
+ ++j;
+ continue;
+ }
+ if (c1 < c2)
+ return (i);
+ // c1 > c2
+ return -1;
+ }
+ }
private static final Primitive _STRING_LESS_THAN = new pf__string_less_than();
private static final class pf__string_less_than extends Primitive {
pf__string_less_than() {
@@ -236,44 +242,18 @@
}
@Override
- public LispObject execute(LispObject[] args) {
- if (args.length != 6)
- return error(new WrongNumberOfArgumentsException(this));
- char[] array1 = args[0].STRING().getStringChars();
- char[] array2 = args[1].STRING().getStringChars();
- int start1 = Fixnum.getValue(args[2]);
- int end1 = Fixnum.getValue(args[3]);
- int start2 = Fixnum.getValue(args[4]);
- int end2 = Fixnum.getValue(args[5]);
- int i = start1;
- int j = start2;
- while (true) {
- if (i == end1) {
- // Reached end of string1.
- if (j == end2)
- return NIL; // Strings are identical.
- return Fixnum.getInstance(i);
- }
- if (j == end2) {
- // Reached end of string2.
- return NIL;
- }
- char c1 = array1[i];
- char c2 = array2[j];
- if (c1 == c2) {
- ++i;
- ++j;
- continue;
- }
- if (c1 < c2)
- return Fixnum.getInstance(i);
- // c1 > c2
- return NIL;
- }
+ public LispObject execute(LispObject first, LispObject second,
+ LispObject third, LispObject fourth,
+ LispObject fifth, LispObject sixth) {
+ StringIndicesAndChars indicesAndChars =
+ stringIndicesAndChars(first, second, third,
+ fourth, fifth, sixth);
+ int retVal = lessThan(indicesAndChars);
+ return (retVal >= 0) ? Fixnum.getInstance(retVal) : NIL;
}
};
- // ### %string<=
+ // ### %string>
// Case sensitive.
private static final Primitive _STRING_GREATER_THAN = new pf__string_greater_than();
private static final class pf__string_greater_than extends Primitive {
@@ -282,41 +262,48 @@
}
@Override
- public LispObject execute(LispObject[] args) {
- if (args.length != 6)
- return error(new WrongNumberOfArgumentsException(this));
- char[] array1 = args[0].STRING().getStringChars();
- char[] array2 = args[1].STRING().getStringChars();
- int start1 = Fixnum.getValue(args[2]);
- int end1 = Fixnum.getValue(args[3]);
- int start2 = Fixnum.getValue(args[4]);
- int end2 = Fixnum.getValue(args[5]);
- int i = start1;
- int j = start2;
- while (true) {
- if (i == end1) {
- // Reached end of string1.
- return NIL;
- }
- if (j == end2) {
- // Reached end of string2.
- return Fixnum.getInstance(i);
- }
- char c1 = array1[i];
- char c2 = array2[j];
- if (c1 == c2) {
- ++i;
- ++j;
- continue;
- }
- if (c1 < c2)
- return NIL;
- // c1 > c2
- return Fixnum.getInstance(i);
+ public LispObject execute(LispObject first, LispObject second,
+ LispObject third, LispObject fourth,
+ LispObject fifth, LispObject sixth) {
+ // note the swap of the strings and lengths here..
+ StringIndicesAndChars indicesAndChars =
+ stringIndicesAndChars(second, first,
+ fifth, sixth,
+ third, fourth);
+ int tmp = lessThan(indicesAndChars);
+ if (tmp < 0) {
+ return NIL;
+ }
+ int delta = tmp - indicesAndChars.start1;
+ int retVal = indicesAndChars.start2 + delta;
+ return Fixnum.getInstance(retVal);
+ }
+ };
+ private static int lessThanOrEqual(StringIndicesAndChars indicesAndChars) {
+ int i = indicesAndChars.start1;
+ int j = indicesAndChars.start2;
+ while (true) {
+ if (i == indicesAndChars.end1) {
+ // Reached end of string1.
+ return i;
+ }
+ if (j == indicesAndChars.end2) {
+ // Reached end of string2.
+ return -1;
+ }
+ char c1 = indicesAndChars.array1[i];
+ char c2 = indicesAndChars.array2[j];
+ if (c1 == c2) {
+ ++i;
+ ++j;
+ continue;
}
+ if (c1 > c2)
+ return -1;
+ // c1 < c2
+ return (i);
}
- };
-
+ }
// ### %string<=
// Case sensitive.
private static final Primitive _STRING_LE = new pf__string_le();
@@ -326,42 +313,19 @@
}
@Override
- public LispObject execute(LispObject[] args) {
- if (args.length != 6)
- return error(new WrongNumberOfArgumentsException(this));
- char[] array1 = args[0].STRING().getStringChars();
- char[] array2 = args[1].STRING().getStringChars();
- int start1 = Fixnum.getValue(args[2]);
- int end1 = Fixnum.getValue(args[3]);
- int start2 = Fixnum.getValue(args[4]);
- int end2 = Fixnum.getValue(args[5]);
- int i = start1;
- int j = start2;
- while (true) {
- if (i == end1) {
- // Reached end of string1.
- return Fixnum.getInstance(i);
- }
- if (j == end2) {
- // Reached end of string2.
- return NIL;
- }
- char c1 = array1[i];
- char c2 = array2[j];
- if (c1 == c2) {
- ++i;
- ++j;
- continue;
- }
- if (c1 > c2)
- return NIL;
- // c1 < c2
- return Fixnum.getInstance(i);
- }
+ public LispObject execute(LispObject first, LispObject second,
+ LispObject third, LispObject fourth,
+ LispObject fifth, LispObject sixth) {
+
+ StringIndicesAndChars indicesAndChars =
+ stringIndicesAndChars(first, second, third,
+ fourth, fifth, sixth);
+ int retVal = lessThanOrEqual(indicesAndChars);
+ return (retVal >= 0) ? Fixnum.getInstance(retVal) : NIL;
}
};
- // ### %string<=
+ // ### %string>=
// Case sensitive.
private static final Primitive _STRING_GE = new pf__string_ge();
private static final class pf__string_ge extends Primitive {
@@ -370,40 +334,21 @@
}
@Override
- public LispObject execute(LispObject[] args) {
- if (args.length != 6)
- return error(new WrongNumberOfArgumentsException(this));
- char[] array1 = args[0].STRING().getStringChars();
- char[] array2 = args[1].STRING().getStringChars();
- int start1 = Fixnum.getValue(args[2]);
- int end1 = Fixnum.getValue(args[3]);
- int start2 = Fixnum.getValue(args[4]);
- int end2 = Fixnum.getValue(args[5]);
- int i = start1;
- int j = start2;
- while (true) {
- if (i == end1) {
- // Reached end of string1.
- if (j == end2)
- return Fixnum.getInstance(i); // Strings are identical.
- return NIL;
- }
- if (j == end2) {
- // Reached end of string2.
- return Fixnum.getInstance(i);
- }
- char c1 = array1[i];
- char c2 = array2[j];
- if (c1 == c2) {
- ++i;
- ++j;
- continue;
- }
- if (c1 < c2)
- return NIL;
- // c1 > c2
- return Fixnum.getInstance(i);
+ public LispObject execute(LispObject first, LispObject second,
+ LispObject third, LispObject fourth,
+ LispObject fifth, LispObject sixth) {
+ // note the swap of the strings and lengths here..
+ StringIndicesAndChars indicesAndChars =
+ stringIndicesAndChars(second, first,
+ fifth, sixth,
+ third, fourth);
+ int tmp = lessThanOrEqual(indicesAndChars);
+ if (tmp < 0) {
+ return NIL;
}
+ int delta = tmp - indicesAndChars.start1;
+ int retVal = indicesAndChars.start2 + delta;
+ return Fixnum.getInstance(retVal);
}
};
@@ -419,27 +364,22 @@
public LispObject execute(LispObject[] args) {
if (args.length != 6)
return error(new WrongNumberOfArgumentsException(this));
- char[] array1 = args[0].STRING().getStringChars();
- char[] array2 = args[1].STRING().getStringChars();
- int start1 = Fixnum.getValue(args[2]);
- int end1 = Fixnum.getValue(args[3]);
- int start2 = Fixnum.getValue(args[4]);
- int end2 = Fixnum.getValue(args[5]);
- int i = start1;
- int j = start2;
+ StringIndicesAndChars indicesAndChars = stringIndicesAndChars(args);
+ int i = indicesAndChars.start1;
+ int j = indicesAndChars.start2;
while (true) {
- if (i == end1) {
+ if (i == indicesAndChars.end1) {
// Reached end of string1.
- if (j == end2)
+ if (j == indicesAndChars.end2)
return NIL; // Strings are identical.
return Fixnum.getInstance(i);
}
- if (j == end2) {
+ if (j == indicesAndChars.end2) {
// Reached end of string2.
return NIL;
}
- char c1 = LispCharacter.toUpperCase(array1[i]);
- char c2 = LispCharacter.toUpperCase(array2[j]);
+ char c1 = LispCharacter.toUpperCase(indicesAndChars.array1[i]);
+ char c2 = LispCharacter.toUpperCase(indicesAndChars.array2[j]);
if (c1 == c2) {
++i;
++j;
@@ -465,25 +405,20 @@
public LispObject execute(LispObject[] args) {
if (args.length != 6)
return error(new WrongNumberOfArgumentsException(this));
- char[] array1 = args[0].STRING().getStringChars();
- char[] array2 = args[1].STRING().getStringChars();
- int start1 = Fixnum.getValue(args[2]);
- int end1 = Fixnum.getValue(args[3]);
- int start2 = Fixnum.getValue(args[4]);
- int end2 = Fixnum.getValue(args[5]);
- int i = start1;
- int j = start2;
+ StringIndicesAndChars indicesAndChars = stringIndicesAndChars(args);
+ int i = indicesAndChars.start1;
+ int j = indicesAndChars.start2;
while (true) {
- if (i == end1) {
+ if (i == indicesAndChars.end1) {
// Reached end of string1.
return NIL;
}
- if (j == end2) {
+ if (j == indicesAndChars.end2) {
// Reached end of string2.
return Fixnum.getInstance(i);
}
- char c1 = LispCharacter.toUpperCase(array1[i]);
- char c2 = LispCharacter.toUpperCase(array2[j]);
+ char c1 = LispCharacter.toUpperCase(indicesAndChars.array1[i]);
+ char c2 = LispCharacter.toUpperCase(indicesAndChars.array2[j]);
if (c1 == c2) {
++i;
++j;
@@ -509,27 +444,22 @@
public LispObject execute(LispObject[] args) {
if (args.length != 6)
return error(new WrongNumberOfArgumentsException(this));
- char[] array1 = args[0].STRING().getStringChars();
- char[] array2 = args[1].STRING().getStringChars();
- int start1 = Fixnum.getValue(args[2]);
- int end1 = Fixnum.getValue(args[3]);
- int start2 = Fixnum.getValue(args[4]);
- int end2 = Fixnum.getValue(args[5]);
- int i = start1;
- int j = start2;
+ StringIndicesAndChars indicesAndChars = stringIndicesAndChars(args);
+ int i = indicesAndChars.start1;
+ int j = indicesAndChars.start2;
while (true) {
- if (i == end1) {
+ if (i == indicesAndChars.end1) {
// Reached end of string1.
- if (j == end2)
+ if (j == indicesAndChars.end2)
return Fixnum.getInstance(i); // Strings are identical.
return NIL;
}
- if (j == end2) {
+ if (j == indicesAndChars.end2) {
// Reached end of string2.
return Fixnum.getInstance(i);
}
- char c1 = LispCharacter.toUpperCase(array1[i]);
- char c2 = LispCharacter.toUpperCase(array2[j]);
+ char c1 = LispCharacter.toUpperCase(indicesAndChars.array1[i]);
+ char c2 = LispCharacter.toUpperCase(indicesAndChars.array2[j]);
if (c1 == c2) {
++i;
++j;
@@ -555,25 +485,20 @@
public LispObject execute(LispObject[] args) {
if (args.length != 6)
return error(new WrongNumberOfArgumentsException(this));
- char[] array1 = args[0].STRING().getStringChars();
- char[] array2 = args[1].STRING().getStringChars();
- int start1 = Fixnum.getValue(args[2]);
- int end1 = Fixnum.getValue(args[3]);
- int start2 = Fixnum.getValue(args[4]);
- int end2 = Fixnum.getValue(args[5]);
- int i = start1;
- int j = start2;
+ StringIndicesAndChars indicesAndChars = stringIndicesAndChars(args);
+ int i = indicesAndChars.start1;
+ int j = indicesAndChars.start2;
while (true) {
- if (i == end1) {
+ if (i == indicesAndChars.end1) {
// Reached end of string1.
return Fixnum.getInstance(i);
}
- if (j == end2) {
+ if (j == indicesAndChars.end2) {
// Reached end of string2.
return NIL;
}
- char c1 = LispCharacter.toUpperCase(array1[i]);
- char c2 = LispCharacter.toUpperCase(array2[j]);
+ char c1 = LispCharacter.toUpperCase(indicesAndChars.array1[i]);
+ char c2 = LispCharacter.toUpperCase(indicesAndChars.array2[j]);
if (c1 == c2) {
++i;
++j;
More information about the armedbear-cvs
mailing list