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
|
@ -273,6 +273,16 @@ public class DBTest extends BaseTestCase {
|
||||||
IString aisc = db.newString(acs);
|
IString aisc = db.newString(acs);
|
||||||
IString bisc = db.newString(bcs);
|
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(bcs, caseSensitive));
|
||||||
assertSignEquals(expected, aiss.compare(biss, caseSensitive));
|
assertSignEquals(expected, aiss.compare(biss, caseSensitive));
|
||||||
assertSignEquals(expected, aiss.compare(bisc, caseSensitive));
|
assertSignEquals(expected, aiss.compare(bisc, caseSensitive));
|
||||||
|
|
|
@ -15,7 +15,7 @@ package org.eclipse.cdt.internal.core.pdom.db;
|
||||||
|
|
||||||
import java.util.NoSuchElementException;
|
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;
|
import org.eclipse.core.runtime.CoreException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -28,7 +28,8 @@ import org.eclipse.core.runtime.CoreException;
|
||||||
public class LongString implements IString {
|
public class LongString implements IString {
|
||||||
|
|
||||||
private final Database db;
|
private final Database db;
|
||||||
private final int record1;
|
private final int record;
|
||||||
|
private int hash;
|
||||||
|
|
||||||
// Additional fields of first record
|
// Additional fields of first record
|
||||||
private static final int LENGTH = 0; // must be first to match ShortString
|
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;
|
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.db = db;
|
||||||
this.record1 = record1;
|
this.record = record;
|
||||||
}
|
}
|
||||||
|
|
||||||
private interface IWriter {
|
private interface IWriter {
|
||||||
|
@ -81,7 +82,7 @@ public class LongString implements IString {
|
||||||
|
|
||||||
public LongString(Database db, final String string) throws CoreException {
|
public LongString(Database db, final String string) throws CoreException {
|
||||||
this.db = db;
|
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 {
|
public void writeChars(int start, int length, int p) throws CoreException {
|
||||||
for (int i = start; i < start + length; ++i) {
|
for (int i = start; i < start + length; ++i) {
|
||||||
LongString.this.db.putChar(p, string.charAt(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 {
|
public LongString(Database db, final char[] chars) throws CoreException {
|
||||||
this.db = db;
|
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 {
|
public void writeChars(int start, int length, int p) throws CoreException {
|
||||||
for (int i = start; i < start + length; ++i) {
|
for (int i = start; i < start + length; ++i) {
|
||||||
LongString.this.db.putChar(p, chars[i]);
|
LongString.this.db.putChar(p, chars[i]);
|
||||||
|
@ -104,13 +105,13 @@ public class LongString implements IString {
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getRecord() {
|
public int getRecord() {
|
||||||
return record1;
|
return record;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void delete() throws CoreException {
|
public void delete() throws CoreException {
|
||||||
int length = db.getInt(record1 + LENGTH) - NUM_CHARS1;
|
int length = db.getInt(record + LENGTH) - NUM_CHARS1;
|
||||||
int nextRecord = db.getInt(record1 + NEXT1);
|
int nextRecord = db.getInt(record + NEXT1);
|
||||||
db.free(record1);
|
db.free(record);
|
||||||
|
|
||||||
// Middle records
|
// Middle records
|
||||||
while (length > NUM_CHARSN) {
|
while (length > NUM_CHARSN) {
|
||||||
|
@ -125,11 +126,57 @@ public class LongString implements IString {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean equals(Object obj) {
|
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() {
|
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 {
|
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 {
|
private void readChars(int length, IReader reader) throws CoreException {
|
||||||
// First record
|
// First record
|
||||||
int p = record1 + CHARS1;
|
int p = record + CHARS1;
|
||||||
for (int i = 0; i < NUM_CHARS1; ++i) {
|
for (int i = 0; i < NUM_CHARS1; ++i) {
|
||||||
reader.appendChar(db.getChar(p));
|
reader.appendChar(db.getChar(p));
|
||||||
p += 2;
|
p += 2;
|
||||||
}
|
}
|
||||||
length -= NUM_CHARS1;
|
length -= NUM_CHARS1;
|
||||||
int nextRecord = db.getInt(record1 + NEXT1);
|
int nextRecord = db.getInt(record + NEXT1);
|
||||||
|
|
||||||
// Middle records
|
// Middle records
|
||||||
while (length > NUM_CHARSN) {
|
while (length > NUM_CHARSN) {
|
||||||
|
@ -282,8 +329,8 @@ public class LongString implements IString {
|
||||||
int length;
|
int length;
|
||||||
|
|
||||||
public CharIterator() throws CoreException {
|
public CharIterator() throws CoreException {
|
||||||
p = record1 + CHARS1;
|
p = record + CHARS1;
|
||||||
length = db.getInt(record1 + LENGTH);
|
length = db.getInt(record + LENGTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
public char next() throws CoreException {
|
public char next() throws CoreException {
|
||||||
|
@ -294,10 +341,10 @@ public class LongString implements IString {
|
||||||
throw new NoSuchElementException();
|
throw new NoSuchElementException();
|
||||||
}
|
}
|
||||||
if(count == NUM_CHARS1) {
|
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) {
|
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;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -308,7 +355,7 @@ public class LongString implements IString {
|
||||||
}
|
}
|
||||||
|
|
||||||
public char[] getChars() throws CoreException {
|
public char[] getChars() throws CoreException {
|
||||||
int length = db.getInt(record1 + LENGTH);
|
int length = db.getInt(record + LENGTH);
|
||||||
final char[] chars = new char[length];
|
final char[] chars = new char[length];
|
||||||
readChars(length, new IReader() {
|
readChars(length, new IReader() {
|
||||||
int cp = 0;
|
int cp = 0;
|
||||||
|
@ -320,7 +367,7 @@ public class LongString implements IString {
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getString() throws CoreException {
|
public String getString() throws CoreException {
|
||||||
int length = db.getInt(record1 + LENGTH);
|
int length = db.getInt(record + LENGTH);
|
||||||
final StringBuffer buffer = new StringBuffer(length);
|
final StringBuffer buffer = new StringBuffer(length);
|
||||||
readChars(length, new IReader() {
|
readChars(length, new IReader() {
|
||||||
public void appendChar(char c) {
|
public void appendChar(char c) {
|
||||||
|
|
|
@ -25,6 +25,7 @@ public class ShortString implements IString {
|
||||||
|
|
||||||
private final Database db;
|
private final Database db;
|
||||||
private final int record;
|
private final int record;
|
||||||
|
private int hash;
|
||||||
|
|
||||||
private static final int LENGTH = 0;
|
private static final int LENGTH = 0;
|
||||||
private static final int CHARS = 4;
|
private static final int CHARS = 4;
|
||||||
|
@ -152,9 +153,24 @@ public class ShortString implements IString {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compatible with {@link String#hashCode()}
|
||||||
|
*/
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
// Custom hash code function to allow DBStrings in hashmaps.
|
int h = hash;
|
||||||
return record;
|
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 {
|
public int compare(char[] other, boolean caseSensitive) throws CoreException {
|
||||||
|
|
Loading…
Add table
Reference in a new issue