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:
parent
e6c6d81bdd
commit
8429b3fcd5
28 changed files with 425 additions and 139 deletions
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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());
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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]);
|
||||
}
|
||||
|
|
|
@ -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 < string
|
||||
* <li> 0 if this == string
|
||||
* <li> 1 if this > 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 < string
|
||||
* <li> 0 if this == string
|
||||
* <li> 1 if this > 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 < chars
|
||||
* <li> 0 if this == chars
|
||||
* <li> 1 if this > 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 < chars
|
||||
* <li> 0 if this has a prefix chars
|
||||
* <li> 1 if this > 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>
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue