1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-24 01:15:29 +02:00

175275 (facilitate case-insensitive search of b-tree indices): apply fix

This commit is contained in:
Andrew Ferguson 2007-02-23 17:05:44 +00:00
parent e6c6d81bdd
commit 8429b3fcd5
28 changed files with 425 additions and 139 deletions

View file

@ -7,24 +7,38 @@
*
* Contributors:
* QNX Software Systems - initial API and implementation
* Andrew Ferguson (Symbian)
*******************************************************************************/
package org.eclipse.cdt.internal.pdom.tests;
import java.io.File;
import java.util.Random;
import junit.framework.TestCase;
import junit.framework.Test;
import org.eclipse.cdt.core.testplugin.CTestPlugin;
import org.eclipse.cdt.core.testplugin.util.BaseTestCase;
import org.eclipse.cdt.internal.core.pdom.db.BTree;
import org.eclipse.cdt.internal.core.pdom.db.Database;
import org.eclipse.cdt.internal.core.pdom.db.IBTreeComparator;
import org.eclipse.cdt.internal.core.pdom.db.IBTreeVisitor;
import org.eclipse.cdt.internal.core.pdom.db.IString;
import org.eclipse.cdt.internal.core.pdom.db.ShortString;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
public class DBTest extends TestCase {
public class DBTest extends BaseTestCase {
protected Database db;
protected void setUp() throws Exception {
super.setUp();
db = new Database(getTestDir().append(getName()+System.currentTimeMillis()+".dat").toFile());
}
public static Test suite() {
return suite(DBTest.class);
}
protected IPath getTestDir() {
IPath path = CTestPlugin.getDefault().getStateLocation().append("tests/");
File file = path.toFile();
@ -33,11 +47,13 @@ public class DBTest extends TestCase {
return path;
}
public void test1() throws Exception {
// Tests block size and simple first block
File f = getTestDir().append("test1.dat").toFile();
f.delete();
Database db = new Database(f);
protected void tearDown() throws Exception {
if(!db.getLocation().delete()) {
db.getLocation().deleteOnExit();
}
}
public void testBlockSizeAndFirstBlock() throws Exception {
assertEquals(0, db.getVersion());
final int realsize = 42;
@ -51,12 +67,7 @@ public class DBTest extends TestCase {
assertEquals(mem - Database.INT_SIZE + blocksize, db.getInt(((Database.CHUNK_SIZE - blocksize) / Database.MIN_SIZE) * Database.INT_SIZE));
}
public void test2() throws Exception {
// Tests free block linking
File f = getTestDir().append("test2.dat").toFile();
f.delete();
Database db = new Database(f);
public void testFreeBlockLinking() throws Exception {
final int realsize = 42;
final int blocksize = (realsize / Database.MIN_SIZE + 1) * Database.MIN_SIZE;
@ -71,12 +82,7 @@ public class DBTest extends TestCase {
assertEquals(0, db.getInt(mem1 + Database.INT_SIZE));
}
public void test3() throws Exception {
//
File f = getTestDir().append("test2.dat").toFile();
f.delete();
Database db = new Database(f);
public void testSimpleAllocationLifecycle() throws Exception {
int mem1 = db.malloc(42);
db.free(mem1);
int mem2 = db.malloc(42);
@ -94,7 +100,7 @@ public class DBTest extends TestCase {
}
public int compare(int record) throws CoreException {
return db.getString(db.getInt(record + 4)).compare(key);
return db.getString(db.getInt(record + 4)).compare(key, true);
}
public boolean visit(int record) throws CoreException {
@ -108,7 +114,7 @@ public class DBTest extends TestCase {
}
public void testStrings() throws Exception {
public void testStringsInBTree() throws Exception {
// Tests inserting and retrieving strings
File f = getTestDir().append("testStrings.dat").toFile();
f.delete();
@ -144,7 +150,7 @@ public class DBTest extends TestCase {
public int compare(int record1, int record2) throws CoreException {
IString string1 = db.getString(db.getInt(record1 + 4));
IString string2 = db.getString(db.getInt(record2 + 4));
return string1.compare(string2);
return string1.compare(string2, true);
}
};
BTree btree = new BTree(db, Database.DATA_AREA, comparator);
@ -168,5 +174,89 @@ public class DBTest extends TestCase {
assertTrue(rname.equals(name));
}
}
private final int GT = 1, LT = -1, EQ = 0;
public void testShortStringComparison() throws CoreException {
Random r= new Random(90210);
assertCMP("", EQ, "", true);
assertCMP("", EQ, "", false);
doTrials(1000, 1, ShortString.MAX_LENGTH, r, true);
doTrials(1000, 1, ShortString.MAX_LENGTH, r, false);
assertCMP("a", LT, "b", true);
assertCMP("aa", LT, "ab", true);
assertCMP("a", EQ, "a", true);
assertCMP("a", GT, "A", true);
assertCMP("aa", GT, "aA", true);
assertCMP("a", GT, "B", true);
assertCMP("a", EQ, "a", false);
assertCMP("a", EQ, "A", false);
}
public void testLongStringComparison() throws CoreException {
Random r= new Random(314159265);
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++) {
String a = randomString(min, max, r);
String b = randomString(min, max, r);
int expected = caseSensitive ? a.compareTo(b) : a.compareToIgnoreCase(b);
assertCMP(a, expected, b, caseSensitive);
}
System.out.print("Trials: "+n+" Max length: "+max+" ignoreCase: "+!caseSensitive);
System.out.println(" Time: "+(System.currentTimeMillis()-start));
}
private String randomString(int min, int max, Random r) {
StringBuffer result = new StringBuffer();
int len = min + r.nextInt(max-min);
for(int i=0; i<len; i++) {
result.append(randomChar(r));
}
return result.toString();
}
private char randomChar(Random r) {
// we only match String.compareToIgnoreCase behaviour within this limited range
return (char) (32 + r.nextInt(40));
}
private void assertCMP(String a, int expected, String b, boolean caseSensitive)
throws CoreException
{
char[] acs = a.toCharArray();
char[] bcs = b.toCharArray();
IString aiss = db.newString(a);
IString biss = db.newString(b);
IString aisc = db.newString(acs);
IString bisc = db.newString(bcs);
assertSignEquals(expected, aiss.compare(bcs, caseSensitive));
assertSignEquals(expected, aiss.compare(biss, caseSensitive));
assertSignEquals(expected, aiss.compare(bisc, caseSensitive));
assertSignEquals(expected, aiss.compare(b, caseSensitive));
assertSignEquals(expected, aiss.comparePrefix(bcs, caseSensitive));
assertSignEquals(expected, -biss.compare(acs, caseSensitive));
assertSignEquals(expected, -biss.compare(aiss, caseSensitive));
assertSignEquals(expected, -biss.compare(aisc, caseSensitive));
assertSignEquals(expected, -biss.compare(a, caseSensitive));
assertSignEquals(expected, -biss.comparePrefix(acs, caseSensitive));
}
private void assertSignEquals(int a, int b) {
a= a<0 ? -1 : (a>0 ? 1 : 0);
b= b<0 ? -1 : (b>0 ? 1 : 0);
assertEquals(a, b);
}
}

View file

@ -23,6 +23,7 @@ public class PDOMTests extends TestSuite {
public static Test suite() {
TestSuite suite = new PDOMTests();
suite.addTest(DBTest.suite());
suite.addTest(PDOMSearchTest.suite());
suite.addTestSuite(EnumerationTests.class);
suite.addTestSuite(ClassTests.class);

View file

@ -258,7 +258,7 @@ public interface IIndex {
* @return an array of bindings with the prefix
* @throws CoreException
*/
public IIndexBinding[] findBindingsForPrefix(char[] prefix, IndexFilter filter) throws CoreException;
public IIndexBinding[] findBindingsForPrefix(char[] prefix, IndexFilter filter, boolean caseSensitive) throws CoreException;
/**
* Searches for all names that resolve to the given binding. You can limit the result to references, declarations

View file

@ -1323,7 +1323,7 @@ public class CVisitor {
IndexFilter filter = IndexFilter
.getFilter(ILinkage.C_LINKAGE_ID);
IBinding[] bindings = prefix ? index.findBindingsForPrefix(
name.toCharArray(), filter) : index.findBindings(
name.toCharArray(), filter, false) : index.findBindings(
name.toCharArray(), filter,
new NullProgressMonitor());

View file

@ -1046,7 +1046,7 @@ public class CPPSemantics {
try {
IndexFilter filter = IndexFilter.getFilter(ILinkage.CPP_LINKAGE_ID);
IBinding[] bindings = data.prefixLookup ?
index.findBindingsForPrefix(data.astName.toCharArray(), filter) :
index.findBindingsForPrefix(data.astName.toCharArray(), filter, false) :
index.findBindings(data.astName.toCharArray(), filter, new NullProgressMonitor());
mergeResults(data, bindings, true);
useASTResults = false;

View file

@ -430,9 +430,9 @@ public class CIndex implements IIndex {
};
}
public IIndexBinding[] findBindingsForPrefix(char[] prefix, IndexFilter filter) throws CoreException {
public IIndexBinding[] findBindingsForPrefix(char[] prefix, IndexFilter filter, boolean caseSensitive) throws CoreException {
if(SPECIALCASE_SINGLES && fFragments.length==1) {
return fFragments[0].findBindingsForPrefix(prefix, filter);
return fFragments[0].findBindingsForPrefix(prefix, filter, caseSensitive);
} else {
List result = new ArrayList();
ILinkage[] linkages = Linkage.getAllLinkages();
@ -441,7 +441,7 @@ public class CIndex implements IIndex {
IIndexFragmentBinding[][] fragmentBindings = new IIndexFragmentBinding[fPrimaryFragmentCount][];
for (int i = 0; i < fPrimaryFragmentCount; i++) {
try {
IBinding[] part = fFragments[i].findBindingsForPrefix(prefix, retargetFilter(linkages[j], filter));
IBinding[] part = fFragments[i].findBindingsForPrefix(prefix, retargetFilter(linkages[j], filter), caseSensitive);
fragmentBindings[i] = new IIndexFragmentBinding[part.length];
System.arraycopy(part, 0, fragmentBindings[i], 0, part.length);
} catch (CoreException e) {

View file

@ -99,7 +99,7 @@ final public class EmptyCIndex implements IIndex {
return null;
}
public IIndexBinding[] findBindingsForPrefix(char[] prefix, IndexFilter filter) {
public IIndexBinding[] findBindingsForPrefix(char[] prefix, IndexFilter filter, boolean caseSensitive) {
return IIndexBinding.EMPTY_INDEX_BINDING_ARRAY;
}

View file

@ -150,7 +150,7 @@ public interface IIndexFragment {
/**
* Returns all bindings with the given prefix, accepted by the given filter
*/
IIndexFragmentBinding[] findBindingsForPrefix(char[] prefix, IndexFilter filter) throws CoreException;
IIndexFragmentBinding[] findBindingsForPrefix(char[] prefix, IndexFilter filter, boolean caseSensitive) throws CoreException;
/**
* Returns the linkages that are contained in this fragment

View file

@ -351,7 +351,7 @@ public class PDOM extends PlatformObject implements IIndexFragment, IPDOM {
bindings.add(linkage);
for (int i=0; i < names.length; i++) {
char[] name= names[i];
BindingCollector collector= new BindingCollector(linkage, name, filter, false);
BindingCollector collector= new BindingCollector(linkage, name, filter, false, true);
for (Iterator in = bindings.iterator(); in.hasNext();) {
PDOMNode node= (PDOMNode) in.next();
node.accept(collector);
@ -607,12 +607,12 @@ public class PDOM extends PlatformObject implements IIndexFragment, IPDOM {
return fPath;
}
public IIndexFragmentBinding[] findBindingsForPrefix(char[] prefix, IndexFilter filter) throws CoreException {
public IIndexFragmentBinding[] findBindingsForPrefix(char[] prefix, IndexFilter filter, boolean caseSensitive) throws CoreException {
ArrayList result = new ArrayList();
for (Iterator iter = fLinkageIDCache.values().iterator(); iter.hasNext();) {
PDOMLinkage linkage = (PDOMLinkage) iter.next();
if (filter.acceptLinkage(linkage)) {
IBinding[] bindings = linkage.findBindingsForPrefix(prefix, filter);
IBinding[] bindings = linkage.findBindingsForPrefix(prefix, filter, caseSensitive);
for (int j = 0; j < bindings.length; j++) {
result.add(bindings[j]);
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2006 QNX Software Systems and others.
* Copyright (c) 2006, 2007 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@ -7,6 +7,7 @@
*
* Contributors:
* QNX - Initial API and implementation
* Andrew Ferguson (Symbian)
*******************************************************************************/
package org.eclipse.cdt.internal.core.pdom.db;
@ -30,47 +31,51 @@ public interface IString {
/**
* Compare this IString record and the specified IString record
* @param chars
* @param caseSensitive whether to compare in a case-sensitive way
* @return <ul><li> -1 if this &lt; string
* <li> 0 if this == string
* <li> 1 if this &gt; string
* </ul>
* @throws CoreException
*/
public int compare(IString string) throws CoreException;
public int compare(IString string, boolean caseSensitive) throws CoreException;
/**
* Compare this IString record and the specified String object
* @param chars
* @param caseSensitive whether to compare in a case-sensitive way
* @return <ul><li> -1 if this &lt; string
* <li> 0 if this == string
* <li> 1 if this &gt; string
* </ul>
* @throws CoreException
*/
public int compare(String string) throws CoreException;
public int compare(String string, boolean caseSensitive) throws CoreException;
/**
* Compare this IString record and the specified character array
* @param chars
* @param caseSensitive whether to compare in a case-sensitive way
* @return <ul><li> -1 if this &lt; chars
* <li> 0 if this == chars
* <li> 1 if this &gt; chars
* </ul>
* @throws CoreException
*/
public int compare(char[] chars) throws CoreException;
public int compare(char[] chars, boolean caseSensitive) throws CoreException;
/**
* Compare this IString record and the specified character array
* @param chars
* @param caseSensitive whether to compare in a case-sensitive way
* @return <ul><li> -1 if this &lt; chars
* <li> 0 if this has a prefix chars
* <li> 1 if this &gt; chars and does not have the prefix
* </ul>
* @throws CoreException
*/
public int comparePrefix(char[] name) throws CoreException;
public int comparePrefix(char[] name, boolean caseSensitive) throws CoreException;
/**
* Get an equivalent character array to this IString record<p>

View file

@ -7,10 +7,13 @@
*
* Contributors:
* QNX - Initial API and implementation
* Andrew Ferguson (Symbian)
*******************************************************************************/
package org.eclipse.cdt.internal.core.pdom.db;
import java.util.NoSuchElementException;
import org.eclipse.cdt.internal.core.pdom.dom.PDOMNotImplementedError;
import org.eclipse.core.runtime.CoreException;
@ -128,33 +131,112 @@ public class LongString implements IString {
return record1;
}
public int compare(IString string) throws CoreException {
public int compare(IString string, boolean caseSensitive) throws CoreException {
if (string instanceof LongString)
return compare((LongString)string);
return compare((LongString)string, caseSensitive);
else if (string instanceof ShortString)
return compare((ShortString)string);
return compare((ShortString)string, caseSensitive);
else
throw new IllegalArgumentException();
}
public int compare(LongString string) throws CoreException {
throw new PDOMNotImplementedError();
public int compare(char[] other, boolean caseSensitive) throws CoreException {
CharIterator i1 = new CharIterator();
int i2 = 0;
int n2 = other.length;
while (i1.hasNext() && i2 < n2) {
int cmp= ShortString.compareChars(i1.next(), other[i2], caseSensitive);
if(cmp!=0)
return cmp;
++i2;
}
if (!i1.hasNext() && i2 != n2)
return -1;
else if (i2 == n2 && i1.hasNext())
return 1;
else
return 0;
}
public int compare(ShortString string) throws CoreException {
throw new PDOMNotImplementedError();
public int compare(ShortString other, boolean caseSensitive) throws CoreException {
CharIterator i1 = new CharIterator();
int index2 = 0;
int length2 = other.getLength();
while (i1.hasNext() && index2<length2) {
int cmp= ShortString.compareChars(i1.next(), other.charAt(index2), caseSensitive);
if(cmp!=0)
return cmp;
index2++;
}
if (!i1.hasNext() && index2 != length2)
return -1;
else if (index2 == length2 && i1.hasNext())
return 1;
else
return 0;
}
public int compare(String string) throws CoreException {
throw new PDOMNotImplementedError();
public int compare(LongString other, boolean caseSensitive) throws CoreException {
CharIterator i1 = new CharIterator();
CharIterator i2 = other.new CharIterator();
while (i1.hasNext() && i2.hasNext()) {
int cmp= ShortString.compareChars(i1.next(), i2.next(), caseSensitive);
if(cmp!=0)
return cmp;
}
if (!i1.hasNext() && i2.hasNext())
return -1;
else if (!i2.hasNext() && i1.hasNext())
return 1;
else
return 0;
}
public int compare(String other, boolean caseSensitive) throws CoreException {
CharIterator i1 = new CharIterator();
int i2 = 0;
int n2 = other.length();
while (i1.hasNext() && i2 < n2) {
int cmp= ShortString.compareChars(i1.next(), other.charAt(i2), caseSensitive);
if(cmp!=0)
return cmp;
++i2;
}
if (!i1.hasNext() && i2 != n2)
return -1;
else if (i2 == n2 && i1.hasNext())
return 1;
else
return 0;
}
public int compare(char[] chars) throws CoreException {
throw new PDOMNotImplementedError();
}
public int comparePrefix(char[] other, boolean caseSensitive) throws CoreException {
CharIterator i1 = new CharIterator();
int i2 = 0;
int n2 = other.length;
while (i1.hasNext() && i2 < n2) {
int cmp= ShortString.compareChars(i1.next(), other[i2], caseSensitive);
if(cmp!=0)
return cmp;
++i2;
}
public int comparePrefix(char[] name) {
throw new PDOMNotImplementedError();
if (!i1.hasNext() && i2 != n2)
return -1;
else
return 0;
}
private interface IReader {
@ -190,6 +272,40 @@ public class LongString implements IString {
}
}
/**
* Convenience class for sequential access to LongString characters
*/
private class CharIterator {
int p;
int count;
int length;
public CharIterator() throws CoreException {
p = record1 + CHARS1;
length = db.getInt(record1 + LENGTH);
}
public char next() throws CoreException {
char result = db.getChar(p);
p += 2;
count++;
if(count>length) {
throw new NoSuchElementException();
}
if(count == NUM_CHARS1) {
p = db.getInt(record1 + NEXT1) + CHARSN;
}
if(count > NUM_CHARS1 && ((count-NUM_CHARS1) % NUM_CHARSN)==0) {
p = db.getInt(record1 + NEXTN) + CHARSN;
}
return result;
}
public boolean hasNext() {
return count<length;
}
}
public char[] getChars() throws CoreException {
int length = db.getInt(record1 + LENGTH);
final char[] chars = new char[length];

View file

@ -7,6 +7,7 @@
*
* Contributors:
* QNX - Initial API and implementation
* Andrew Ferguson (Symbian)
*******************************************************************************/
package org.eclipse.cdt.internal.core.pdom.db;
@ -154,17 +155,42 @@ public class ShortString implements IString {
// Custom hash code function to allow DBStrings in hashmaps.
return record;
}
public int compare(char[] other, boolean caseSensitive) throws CoreException {
Chunk chunk = db.getChunk(record);
int i1 = record + CHARS;
int i2 = 0;
int n1 = i1 + chunk.getInt(record + LENGTH) * 2;
int n2 = other.length;
while (i1 < n1 && i2 < n2) {
int cmp= compareChars(chunk.getChar(i1), other[i2], caseSensitive);
if(cmp!=0)
return cmp;
i1 += 2;
++i2;
}
public int compare(IString string) throws CoreException {
if (i1 == n1 && i2 != n2)
return -1;
else if (i2 == n2 && i1 != n1)
return 1;
else
return 0;
}
public int compare(IString string, boolean caseSensitive) throws CoreException {
if (string instanceof ShortString)
return compare((ShortString)string);
return compare((ShortString)string, caseSensitive);
else if (string instanceof LongString)
return - ((LongString)string).compare(this);
return - ((LongString)string).compare(this, caseSensitive);
else
throw new IllegalArgumentException();
}
public int compare(ShortString other) throws CoreException {
public int compare(ShortString other, boolean caseSensitive) throws CoreException {
Chunk chunk1 = db.getChunk(record);
Chunk chunk2 = other.db.getChunk(other.record);
@ -174,13 +200,9 @@ public class ShortString implements IString {
int n2 = i2 + chunk2.getInt(other.record + LENGTH) * 2;
while (i1 < n1 && i2 < n2) {
char c1 = chunk1.getChar(i1);
char c2 = chunk2.getChar(i2);
if (c1 < c2)
return -1;
if (c1 > c2)
return 1;
int cmp= compareChars(chunk1.getChar(i1), chunk2.getChar(i2), caseSensitive);
if(cmp!=0)
return cmp;
i1 += 2;
i2 += 2;
@ -194,22 +216,18 @@ public class ShortString implements IString {
return 0;
}
public int compare(char[] other) throws CoreException {
public int compare(String other, boolean caseSensitive) throws CoreException {
Chunk chunk = db.getChunk(record);
int i1 = record + CHARS;
int i2 = 0;
int n1 = i1 + chunk.getInt(record + LENGTH) * 2;
int n2 = other.length;
int n2 = other.length();
while (i1 < n1 && i2 < n2) {
char c1 = chunk.getChar(i1);
char c2 = other[i2];
if (c1 < c2)
return -1;
if (c1 > c2)
return 1;
int cmp= compareChars(chunk.getChar(i1), other.charAt(i2), caseSensitive);
if(cmp!=0)
return cmp;
i1 += 2;
++i2;
@ -223,7 +241,7 @@ public class ShortString implements IString {
return 0;
}
public int comparePrefix(char[] other) throws CoreException {
public int comparePrefix(char[] other, boolean caseSensitive) throws CoreException {
Chunk chunk = db.getChunk(record);
int i1 = record + CHARS;
@ -232,13 +250,9 @@ public class ShortString implements IString {
int n2 = other.length;
while (i1 < n1 && i2 < n2) {
char c1 = chunk.getChar(i1);
char c2 = other[i2];
if (c1 < c2)
return -1;
if (c1 > c2)
return 1;
int cmp= compareChars(chunk.getChar(i1), other[i2], caseSensitive);
if(cmp!=0)
return cmp;
i1 += 2;
++i2;
@ -249,34 +263,76 @@ public class ShortString implements IString {
else
return 0;
}
public int compare(String other) throws CoreException {
Chunk chunk = db.getChunk(record);
int i1 = record + CHARS;
int i2 = 0;
int n1 = i1 + chunk.getInt(record + LENGTH) * 2;
int n2 = other.length();
while (i1 < n1 && i2 < n2) {
char c1 = chunk.getChar(i1);
char c2 = other.charAt(i2);
if (c1 < c2)
return -1;
if (c1 > c2)
return 1;
i1 += 2;
++i2;
}
if (i1 == n1 && i2 != n2)
return -1;
else if (i2 == n2 && i1 != n1)
return 1;
else
return 0;
public char charAt(int i) throws CoreException {
int ptr = record + CHARS + (i*2);
return db.getChar(ptr);
}
public int getLength() throws CoreException {
return db.getInt(record + LENGTH);
}
/**
* Compare characters case-sensitively, or case-insensitively.
*
* <b>Limitation</b> This only maps the range a-z,A-Z onto each other
* @param a a character
* @param b a character
* @param caseSensitive whether to compare case-sensitively
* @return
* <ul>
* <li>-1 if a < b
* <li>0 if a == b
* <li>1 if a > b
* </ul>
*/
public static int compareChars(char a, char b, boolean caseSensitive) {
if(caseSensitive) {
if (a < b)
return -1;
if (a > b)
return 1;
} else {
if (a != b) {
a= a >= 'a' && a <='z' ? (char) (a - 32) : a;
b= b >= 'a' && b <='z' ? (char) (b - 32) : b;
if (a < b)
return -1;
if (a > b)
return 1;
}
}
return 0;
}
/* TODO - this is more correct than the above implementation, but we need to
* benchmark first.
*
* public static int compareChars(char a, char b, boolean caseSensitive) {
if(caseSensitive) {
if (a < b)
return -1;
if (a > b)
return 1;
} else {
if (a != b) {
a = Character.toUpperCase(a);
b = Character.toUpperCase(b);
if (a != b) {
a = Character.toLowerCase(a);
b = Character.toLowerCase(b);
if (a != b) {
if (a < b)
return -1;
if (a > b)
return 1;
}
}
}
}
return 0;
}
*/
}
}

View file

@ -8,6 +8,7 @@
* Contributors:
* QNX - Initial API and implementation
* Markus Schorn (Wind River Systems)
* Andrew Ferguson (Symbian)
*******************************************************************************/
package org.eclipse.cdt.internal.core.pdom.dom;
@ -27,15 +28,15 @@ public final class BindingCollector extends NamedNodeCollector {
* Collects all bindings with given name.
*/
public BindingCollector(PDOMLinkage linkage, char[] name) {
this(linkage, name, null, false);
this(linkage, name, null, false, true);
}
/**
* Collects all bindings with given name, passing the filter. If prefixLookup is set to
* <code>true</code> a binding is considered if its name starts with the given prefix.
*/
public BindingCollector(PDOMLinkage linkage, char[] name, IndexFilter filter, boolean prefixLookup) {
super(linkage, name, prefixLookup);
public BindingCollector(PDOMLinkage linkage, char[] name, IndexFilter filter, boolean prefixLookup, boolean caseSensitive) {
super(linkage, name, prefixLookup, caseSensitive);
this.filter= filter;
}

View file

@ -34,7 +34,8 @@ public class FindBinding {
public int compare(int record1, int record2) throws CoreException {
IString nm1 = PDOMNamedNode.getDBName(pdom, record1);
IString nm2 = PDOMNamedNode.getDBName(pdom, record2);
int cmp = nm1.compare(nm2);
int cmp= nm1.compare(nm2, false);
cmp= cmp==0 ? nm1.compare(nm2, true) : cmp;
if(cmp == 0) {
int t1 = PDOMNamedNode.getNodeType(pdom, record1);
int t2 = PDOMNamedNode.getNodeType(pdom, record2);
@ -49,7 +50,8 @@ public class FindBinding {
btree.accept(new IBTreeVisitor() {
public int compare(int record) throws CoreException {
IString nm1 = PDOMNamedNode.getDBName(pdom, record);
return nm1.compare(name);
int cmp= nm1.compare(name, false);
return cmp==0 ? nm1.compare(name, true) : cmp;
}
public boolean visit(int record) throws CoreException {
PDOMNamedNode nnode = (PDOMNamedNode) PDOMLinkage.getLinkage(pdom, record).getNode(record);

View file

@ -26,6 +26,7 @@ public class NamedNodeCollector implements IBTreeVisitor, IPDOMVisitor {
private final PDOMLinkage linkage;
private final char[] name;
private final boolean prefixLookup;
private final boolean caseSensitive;
private List nodes = new ArrayList();
@ -33,17 +34,18 @@ public class NamedNodeCollector implements IBTreeVisitor, IPDOMVisitor {
* Collects all nodes with given name.
*/
public NamedNodeCollector(PDOMLinkage linkage, char[] name) {
this(linkage, name, false);
this(linkage, name, false, true);
}
/**
* Collects all nodes with given name, passing the filter. If prefixLookup is set to
* <code>true</code> a binding is considered if its name starts with the given prefix.
*/
public NamedNodeCollector(PDOMLinkage linkage, char[] name, boolean prefixLookup) {
this.name = name;
public NamedNodeCollector(PDOMLinkage linkage, char[] name, boolean prefixLookup, boolean caseSensitive) {
this.name= name;
this.linkage= linkage;
this.prefixLookup = prefixLookup;
this.prefixLookup= prefixLookup;
this.caseSensitive= caseSensitive;
}
final public int compare(int record) throws CoreException {
@ -52,10 +54,20 @@ public class NamedNodeCollector implements IBTreeVisitor, IPDOMVisitor {
}
private int compare(PDOMNamedNode node) throws CoreException {
int cmp;
if (prefixLookup) {
return node.getDBName().comparePrefix(name);
cmp= node.getDBName().comparePrefix(name, false);
if(caseSensitive) {
cmp= cmp==0 ? node.getDBName().comparePrefix(name, true) : cmp;
}
return cmp;
} else {
cmp= node.getDBName().compare(name, false);
if(caseSensitive) {
cmp= cmp==0 ? node.getDBName().compare(name, true) : cmp;
}
}
return node.getDBName().compare(name);
return cmp;
}
final public boolean visit(int record) throws CoreException {

View file

@ -250,7 +250,7 @@ public abstract class PDOMBinding extends PDOMNamedNode implements IIndexFragmen
int cmp = 0;
do {
IString s0 = b0.getDBName(), s1 = b1.getDBName();
cmp = s0.compare(s1);
cmp = s0.compare(s1, true);
if(cmp==0) {
b0 = (PDOMBinding) b0.getParentBinding();
b1 = (PDOMBinding) b1.getParentBinding();

View file

@ -67,7 +67,7 @@ public class PDOMFile implements IIndexFragmentFile {
public int compare(int record1, int record2) throws CoreException {
IString name1 = db.getString(db.getInt(record1 + LOCATION_REPRESENTATION));
IString name2 = db.getString(db.getInt(record2 + LOCATION_REPRESENTATION));
return name1.compare(name2);
return name1.compare(name2, true);
}
}
@ -358,7 +358,7 @@ public class PDOMFile implements IIndexFragmentFile {
public int compare(int record) throws CoreException {
IString name = db.getString(db.getInt(record + PDOMFile.LOCATION_REPRESENTATION));
return name.compare(rawKey);
return name.compare(rawKey, true);
}
public boolean visit(int record) throws CoreException {

View file

@ -252,8 +252,8 @@ public abstract class PDOMLinkage extends PDOMNamedNode implements IIndexLinkage
protected abstract boolean isFileLocalBinding(IBinding binding) throws DOMException;
public abstract int getBindingType(IBinding binding);
public IBinding[] findBindingsForPrefix(char[] prefix, IndexFilter filter) throws CoreException {
BindingCollector visitor = new BindingCollector(this, prefix, filter, true);
public IBinding[] findBindingsForPrefix(char[] prefix, IndexFilter filter, boolean caseSensitive) throws CoreException {
BindingCollector visitor = new BindingCollector(this, prefix, filter, true, caseSensitive);
getIndex().accept(visitor);
return visitor.getBindings();

View file

@ -43,7 +43,10 @@ public class CPPFindBinding extends FindBinding {
btree.accept(new IBTreeVisitor() {
public int compare(int record) throws CoreException {
IString nm1 = PDOMNamedNode.getDBName(pdom, record);
int cmp = nm1.compare(name);
int cmp= nm1.compare(name, false);
cmp= cmp==0 ? nm1.compare(name, true) : cmp;
if(cmp==0) {
int c1 = PDOMNode.getNodeType(pdom, record);
cmp = c1 < c2 ? -1 : (c1 > c2 ? 1 : 0);

View file

@ -107,7 +107,7 @@ class PDOMCPPNamespace extends PDOMCPPBinding implements ICPPNamespace, ICPPName
public IBinding[] find(String name, boolean prefixLookup) {
try {
BindingCollector visitor = new BindingCollector(getLinkageImpl(), name.toCharArray(), null, prefixLookup);
BindingCollector visitor = new BindingCollector(getLinkageImpl(), name.toCharArray(), null, prefixLookup, true);
getIndex().accept(visitor);
return visitor.getBindings();
} catch (CoreException e) {

View file

@ -230,8 +230,8 @@ public class ContentAssistTests extends BaseUITestCase {
results = getResults( cu, c2.indexOf( "::" ) + 2 ); //$NON-NLS-1$
assertEquals( 2, results.length );
assertEquals( "getAbility(void) enum _Ability", results[0].getDisplayString() ); //$NON-NLS-1$
assertEquals( "Strategy(enum _Ability a)", results[1].getDisplayString() ); //$NON-NLS-1$
assertEquals( "getAbility(void) enum _Ability", results[1].getDisplayString() ); //$NON-NLS-1$
assertEquals( "Strategy(enum _Ability a)", results[0].getDisplayString() ); //$NON-NLS-1$
}
public void testBug72559() throws Exception {

View file

@ -38,7 +38,7 @@ public class CompletionTest_ArgumentType_Prefix extends CompletionProposalsBase
public CompletionTest_ArgumentType_Prefix(String name) {
super(name);
// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=109724
setExpectFailure(109724);
// setExpectFailure(109724);
}
public static Test suite() {

View file

@ -38,7 +38,7 @@ public class CompletionTest_ArgumentType_Prefix2 extends CompletionProposalsBas
public CompletionTest_ArgumentType_Prefix2(String name) {
super(name);
// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=109724
setExpectFailure(109724);
// setExpectFailure(109724);
}
public static Test suite() {

View file

@ -40,7 +40,7 @@ public class CompletionTest_ExceptionReference_Prefix extends CompletionProposa
public CompletionTest_ExceptionReference_Prefix(String name) {
super(name);
// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=109724
setExpectFailure(109724);
// setExpectFailure(109724);
}
public static Test suite() {

View file

@ -37,7 +37,7 @@ public class CompletionTest_FieldType_Prefix extends CompletionProposalsBaseTes
public CompletionTest_FieldType_Prefix(String name) {
super(name);
// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=109724
setExpectFailure(109724);
// setExpectFailure(109724);
}
public static Test suite() {

View file

@ -36,7 +36,7 @@ public class CompletionTest_VariableType_Prefix extends CompletionProposalsBase
public CompletionTest_VariableType_Prefix(String name) {
super(name);
// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=109724
setExpectFailure(109724);
// setExpectFailure(109724);
}
public static Test suite() {

View file

@ -327,7 +327,7 @@ public class CompletionTests extends AbstractContentAssistTest {
//void f() {e/*cursor*/
public void testEnums_GlobalScope() throws Exception {
final String[] expected= {
"e11", "e12"
"e11", "e12", "E1"
};
assertCompletionResults(fCursorOffset, expected, true);
}
@ -335,7 +335,7 @@ public class CompletionTests extends AbstractContentAssistTest {
//void C3::f() {e/*cursor*/
public void testEnums_MethodScope() throws Exception {
final String[] expected= {
"e11", "e12", "e21", "e22"
"e11", "e12", "e21", "e22", "E1"
};
assertCompletionResults(fCursorOffset, expected, true);
}

View file

@ -47,7 +47,7 @@ public class CCompletionProposalComparator implements Comparator {
String id1 = c1.getIdString();
String id2 = c2.getIdString();
return id1.compareToIgnoreCase(id2);
return id1.compareTo(id2);
}
}