mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
Proper hashCode() for ShortString and LongString (bug 185343)
This commit is contained in:
parent
3a0b436262
commit
85042a14f6
3 changed files with 96 additions and 23 deletions
|
@ -236,7 +236,7 @@ public class DBTest extends BaseTestCase {
|
|||
doTrials(600, ShortString.MAX_LENGTH+1, ShortString.MAX_LENGTH*2, r, true);
|
||||
doTrials(600, ShortString.MAX_LENGTH+1, ShortString.MAX_LENGTH*2, r, false);
|
||||
}
|
||||
|
||||
|
||||
private void doTrials(int n, int min, int max, Random r, boolean caseSensitive) throws CoreException {
|
||||
long start = System.currentTimeMillis();
|
||||
for(int i=0; i<n; i++) {
|
||||
|
@ -273,6 +273,16 @@ public class DBTest extends BaseTestCase {
|
|||
IString aisc = db.newString(acs);
|
||||
IString bisc = db.newString(bcs);
|
||||
|
||||
assertEquals(a.hashCode(), aiss.hashCode());
|
||||
assertEquals(a.hashCode(), aisc.hashCode());
|
||||
assertEquals(b.hashCode(), biss.hashCode());
|
||||
assertEquals(b.hashCode(), bisc.hashCode());
|
||||
|
||||
assertEquals(aiss, a);
|
||||
assertEquals(aisc, a);
|
||||
assertEquals(biss, b);
|
||||
assertEquals(bisc, b);
|
||||
|
||||
assertSignEquals(expected, aiss.compare(bcs, caseSensitive));
|
||||
assertSignEquals(expected, aiss.compare(biss, caseSensitive));
|
||||
assertSignEquals(expected, aiss.compare(bisc, caseSensitive));
|
||||
|
|
|
@ -15,7 +15,7 @@ package org.eclipse.cdt.internal.core.pdom.db;
|
|||
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
import org.eclipse.cdt.internal.core.pdom.dom.PDOMNotImplementedError;
|
||||
import org.eclipse.cdt.core.CCorePlugin;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
|
||||
/**
|
||||
|
@ -28,7 +28,8 @@ import org.eclipse.core.runtime.CoreException;
|
|||
public class LongString implements IString {
|
||||
|
||||
private final Database db;
|
||||
private final int record1;
|
||||
private final int record;
|
||||
private int hash;
|
||||
|
||||
// Additional fields of first record
|
||||
private static final int LENGTH = 0; // must be first to match ShortString
|
||||
|
@ -43,9 +44,9 @@ public class LongString implements IString {
|
|||
|
||||
private static final int NUM_CHARSN = (Database.MAX_SIZE - CHARSN) / 2;
|
||||
|
||||
public LongString(Database db, int record1) {
|
||||
public LongString(Database db, int record) {
|
||||
this.db = db;
|
||||
this.record1 = record1;
|
||||
this.record = record;
|
||||
}
|
||||
|
||||
private interface IWriter {
|
||||
|
@ -81,7 +82,7 @@ public class LongString implements IString {
|
|||
|
||||
public LongString(Database db, final String string) throws CoreException {
|
||||
this.db = db;
|
||||
this.record1 = createString(string.length(), new IWriter() {
|
||||
this.record = createString(string.length(), new IWriter() {
|
||||
public void writeChars(int start, int length, int p) throws CoreException {
|
||||
for (int i = start; i < start + length; ++i) {
|
||||
LongString.this.db.putChar(p, string.charAt(i));
|
||||
|
@ -93,7 +94,7 @@ public class LongString implements IString {
|
|||
|
||||
public LongString(Database db, final char[] chars) throws CoreException {
|
||||
this.db = db;
|
||||
this.record1 = createString(chars.length, new IWriter() {
|
||||
this.record = createString(chars.length, new IWriter() {
|
||||
public void writeChars(int start, int length, int p) throws CoreException {
|
||||
for (int i = start; i < start + length; ++i) {
|
||||
LongString.this.db.putChar(p, chars[i]);
|
||||
|
@ -104,13 +105,13 @@ public class LongString implements IString {
|
|||
}
|
||||
|
||||
public int getRecord() {
|
||||
return record1;
|
||||
return record;
|
||||
}
|
||||
|
||||
public void delete() throws CoreException {
|
||||
int length = db.getInt(record1 + LENGTH) - NUM_CHARS1;
|
||||
int nextRecord = db.getInt(record1 + NEXT1);
|
||||
db.free(record1);
|
||||
int length = db.getInt(record + LENGTH) - NUM_CHARS1;
|
||||
int nextRecord = db.getInt(record + NEXT1);
|
||||
db.free(record);
|
||||
|
||||
// Middle records
|
||||
while (length > NUM_CHARSN) {
|
||||
|
@ -125,11 +126,57 @@ public class LongString implements IString {
|
|||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
throw new PDOMNotImplementedError();
|
||||
if (obj == this)
|
||||
return true;
|
||||
try {
|
||||
if (obj instanceof LongString) {
|
||||
LongString lstr = (LongString)obj;
|
||||
if (db == lstr.db && record == lstr.record)
|
||||
return true;
|
||||
return compare(lstr, true) == 0;
|
||||
}
|
||||
if (obj instanceof char[]) {
|
||||
return compare((char[]) obj, true) == 0;
|
||||
}
|
||||
if (obj instanceof String) {
|
||||
return compare((String) obj, true) == 0;
|
||||
}
|
||||
} catch (CoreException e) {
|
||||
CCorePlugin.log(e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
private class HashCodeComputer implements IReader {
|
||||
private int fHashcode= 0;
|
||||
|
||||
public int getHashcode() {
|
||||
return fHashcode;
|
||||
}
|
||||
|
||||
public void appendChar(char c) {
|
||||
fHashcode = 31*fHashcode + c;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compatible with {@link String#hashCode()}
|
||||
*/
|
||||
public int hashCode() {
|
||||
return record1;
|
||||
int h = hash;
|
||||
if (h == 0) {
|
||||
HashCodeComputer hcc;
|
||||
try {
|
||||
int length = db.getInt(record + LENGTH);
|
||||
hcc = new HashCodeComputer();
|
||||
readChars(length, hcc);
|
||||
h= hcc.getHashcode();
|
||||
hash = h;
|
||||
} catch (CoreException e) {
|
||||
}
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
public int compare(IString string, boolean caseSensitive) throws CoreException {
|
||||
|
@ -246,13 +293,13 @@ public class LongString implements IString {
|
|||
|
||||
private void readChars(int length, IReader reader) throws CoreException {
|
||||
// First record
|
||||
int p = record1 + CHARS1;
|
||||
int p = record + CHARS1;
|
||||
for (int i = 0; i < NUM_CHARS1; ++i) {
|
||||
reader.appendChar(db.getChar(p));
|
||||
p += 2;
|
||||
}
|
||||
length -= NUM_CHARS1;
|
||||
int nextRecord = db.getInt(record1 + NEXT1);
|
||||
int nextRecord = db.getInt(record + NEXT1);
|
||||
|
||||
// Middle records
|
||||
while (length > NUM_CHARSN) {
|
||||
|
@ -282,8 +329,8 @@ public class LongString implements IString {
|
|||
int length;
|
||||
|
||||
public CharIterator() throws CoreException {
|
||||
p = record1 + CHARS1;
|
||||
length = db.getInt(record1 + LENGTH);
|
||||
p = record + CHARS1;
|
||||
length = db.getInt(record + LENGTH);
|
||||
}
|
||||
|
||||
public char next() throws CoreException {
|
||||
|
@ -294,10 +341,10 @@ public class LongString implements IString {
|
|||
throw new NoSuchElementException();
|
||||
}
|
||||
if(count == NUM_CHARS1) {
|
||||
p = db.getInt(record1 + NEXT1) + CHARSN;
|
||||
p = db.getInt(record + NEXT1) + CHARSN;
|
||||
}
|
||||
if(count > NUM_CHARS1 && ((count-NUM_CHARS1) % NUM_CHARSN)==0) {
|
||||
p = db.getInt(record1 + NEXTN) + CHARSN;
|
||||
p = db.getInt(p-(NUM_CHARSN*2)-4) + CHARSN;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -308,7 +355,7 @@ public class LongString implements IString {
|
|||
}
|
||||
|
||||
public char[] getChars() throws CoreException {
|
||||
int length = db.getInt(record1 + LENGTH);
|
||||
int length = db.getInt(record + LENGTH);
|
||||
final char[] chars = new char[length];
|
||||
readChars(length, new IReader() {
|
||||
int cp = 0;
|
||||
|
@ -320,7 +367,7 @@ public class LongString implements IString {
|
|||
}
|
||||
|
||||
public String getString() throws CoreException {
|
||||
int length = db.getInt(record1 + LENGTH);
|
||||
int length = db.getInt(record + LENGTH);
|
||||
final StringBuffer buffer = new StringBuffer(length);
|
||||
readChars(length, new IReader() {
|
||||
public void appendChar(char c) {
|
||||
|
|
|
@ -25,6 +25,7 @@ public class ShortString implements IString {
|
|||
|
||||
private final Database db;
|
||||
private final int record;
|
||||
private int hash;
|
||||
|
||||
private static final int LENGTH = 0;
|
||||
private static final int CHARS = 4;
|
||||
|
@ -152,9 +153,24 @@ public class ShortString implements IString {
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compatible with {@link String#hashCode()}
|
||||
*/
|
||||
public int hashCode() {
|
||||
// Custom hash code function to allow DBStrings in hashmaps.
|
||||
return record;
|
||||
int h = hash;
|
||||
if (h == 0) {
|
||||
char chars[];
|
||||
try {
|
||||
chars = getChars();
|
||||
final int len = chars.length;
|
||||
for (int i = 0; i < len; i++) {
|
||||
h = 31*h + chars[i];
|
||||
}
|
||||
} catch (CoreException e) {
|
||||
}
|
||||
hash = h;
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
public int compare(char[] other, boolean caseSensitive) throws CoreException {
|
||||
|
|
Loading…
Add table
Reference in a new issue