--- java/src/org/apache/xindice/core/indexer/ValueIndexer.java (revision 474103) +++ java/src/org/apache/xindice/core/indexer/ValueIndexer.java (working copy) @@ -177,6 +177,16 @@ return pattern; } + /** + * Creates new Value object that depends on string parameter and a type of indexer. + * The idea here is that any value of any type should be transformed to a byte array + * in such a way that two Values of the same type are comparable. Value objects are + * compared by comparing their data arrays byte-by-byte, starting from byte with + * index 0. Also, data arrays will behave as array of unsigned bytes with + * values ranging from 0 to 255. + * @param value + * @return new Value object that represents specific value of this indexer type + */ public Value getTypedValue(String value) { if (type != STRING && type != TRIMMED) { value = value.trim(); @@ -189,6 +199,13 @@ try { switch (type) { case INTEGER: + /* + Generally, two integers can be compared byte-by-byte, returning correct results, + except negative numbers which will be always bigger than positive numbers. + To solve this, change the value to be unsigned. Number range changes from + Long.MIN_VALUE / Long.MAX_VALUE to 0 / Long.MAX_VALUE - Long.MIN_VALUE. + This is done by flipping the first bit of the byte with index 0. + */ long l = Long.parseLong(value); b[0] = (byte) ((l >>> 56) & 0xFF); b[1] = (byte) ((l >>> 48) & 0xFF); @@ -198,22 +215,34 @@ b[5] = (byte) ((l >>> 16) & 0xFF); b[6] = (byte) ((l >>> 8) & 0xFF); b[7] = (byte) ((l >>> 0) & 0xFF); + b[0] = (byte) (b[0] ^ 0x80); break; case FLOAT: + /* + Float/Double number are stored according to IEEE standard 754. In short, + float numbers have the folloing format: 1 bit to indicate the sign of + the number, 8 bits for exponent, 23 bits for mantissa, and double + numbers have the following format: 1 bit to indicate the sign of + the number, 11 bits for exponent, 52 bits for mantissa. Both float and + double are normalized, so they can be compared byte-by-byte, except + that negative numbers will be bigger than positive. This is solved by + changing number sign (is is stored in the first bit). + */ double d = Double.parseDouble(value); - int i1 = (int) Math.round(d); - int i2 = (int) Math.round((d - i1) * 1000000000); - b[0] = (byte) ((i1 >>> 24) & 0xFF); - b[1] = (byte) ((i1 >>> 16) & 0xFF); - b[2] = (byte) ((i1 >>> 8) & 0xFF); - b[3] = (byte) ((i1 >>> 0) & 0xFF); - b[4] = (byte) ((i2 >>> 24) & 0xFF); - b[5] = (byte) ((i2 >>> 16) & 0xFF); - b[6] = (byte) ((i2 >>> 8) & 0xFF); - b[7] = (byte) ((i2 >>> 0) & 0xFF); + long bits = Double.doubleToRawLongBits(d); + b[0] = (byte) ((bits >>> 56) & 0xFF); + b[1] = (byte) ((bits >>> 48) & 0xFF); + b[2] = (byte) ((bits >>> 40) & 0xFF); + b[3] = (byte) ((bits >>> 32) & 0xFF); + b[4] = (byte) ((bits >>> 24) & 0xFF); + b[5] = (byte) ((bits >>> 16) & 0xFF); + b[6] = (byte) ((bits >>> 8) & 0xFF); + b[7] = (byte) ((bits >>> 0) & 0xFF); + b[0] = (byte) (b[0] ^ 0x80); break; case BYTE: b[0] = Byte.parseByte(value); + b[0] = (byte) (b[0] ^ 0x80); break; case CHAR: char c = value.charAt(0); --- java/src/org/apache/xindice/core/filer/BTree.java (revision 474103) +++ java/src/org/apache/xindice/core/filer/BTree.java (working copy) @@ -903,7 +903,7 @@ leftIdx = -(leftIdx + 1); } n = Math.min(leftIdx + 1, ptrs.length); - for (int i = 0; i <= n; i++) { + for (int i = 0; i < n; i++) { if (query.testValue(values[i])) { callback.indexInfo(values[i], ptrs[i]); } --- java/src/org/apache/xindice/core/data/Value.java (revision 474103) +++ java/src/org/apache/xindice/core/data/Value.java (working copy) @@ -129,7 +160,7 @@ } public boolean equals(Value value) { - return len == value.len ? compareTo(value) == 0 : false; + return len == value.len && compareTo(value) == 0; } public boolean equals(Object obj) { @@ -154,11 +185,10 @@ byte b1 = data[pos + i]; byte b2 = ddata[dpos + i]; - if (b1 == b2) - continue; - else { - short s1 = (short) (b1 >>> 0); - short s2 = (short) (b2 >>> 0); + if (b1 != b2) { + // get unsigned value + int s1 = ((int) b1) & 0xFF; + int s2 = ((int) b2) & 0xFF; return s1 > s2 ? (i + 1) : -(i + 1); } }