mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-23 22:52:11 +02:00
Bug 362442: Considering all expansions for significant macros.
This commit is contained in:
parent
b680564684
commit
2dea3d4a33
9 changed files with 331 additions and 552 deletions
|
@ -136,10 +136,12 @@ public class DBTest extends BaseTestCase {
|
|||
this.key = key;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compare(long record) throws CoreException {
|
||||
return db.getString(db.getRecPtr(record + 4)).compare(key, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(long record) throws CoreException {
|
||||
this.record = record;
|
||||
return false;
|
||||
|
@ -185,6 +187,7 @@ public class DBTest extends BaseTestCase {
|
|||
};
|
||||
|
||||
IBTreeComparator comparator = new IBTreeComparator() {
|
||||
@Override
|
||||
public int compare(long record1, long record2) throws CoreException {
|
||||
IString string1 = db.getString(db.getRecPtr(record1 + 4));
|
||||
IString string2 = db.getString(db.getRecPtr(record2 + 4));
|
||||
|
@ -221,9 +224,10 @@ public class DBTest extends BaseTestCase {
|
|||
assertCMP("", EQ, "", true);
|
||||
assertCMP("", EQ, "", false);
|
||||
|
||||
doTrials(1000, 1, ShortString.MAX_LENGTH, r, true);
|
||||
|
||||
doTrials(1000, 1, ShortString.MAX_LENGTH, r, false);
|
||||
doTrials(1000, 1, ShortString.MAX_BYTE_LENGTH/2, r, true);
|
||||
doTrials(1000, 1, ShortString.MAX_BYTE_LENGTH/2, r, false);
|
||||
doTrials(1000, 1, ShortString.MAX_BYTE_LENGTH, r, true);
|
||||
doTrials(1000, 1, ShortString.MAX_BYTE_LENGTH, r, false);
|
||||
|
||||
assertCMP("a", LT, "b", true);
|
||||
assertCMP("aa", LT, "ab", true);
|
||||
|
@ -239,8 +243,8 @@ public class DBTest extends BaseTestCase {
|
|||
|
||||
public void testLongStringComparison() throws CoreException {
|
||||
Random r= new Random(314159265);
|
||||
doTrials(100, ShortString.MAX_LENGTH+1, ShortString.MAX_LENGTH*2, r, true);
|
||||
doTrials(100, ShortString.MAX_LENGTH+1, ShortString.MAX_LENGTH*2, r, false);
|
||||
doTrials(100, ShortString.MAX_BYTE_LENGTH+1, ShortString.MAX_BYTE_LENGTH*2, r, true);
|
||||
doTrials(100, ShortString.MAX_BYTE_LENGTH+1, ShortString.MAX_BYTE_LENGTH*2, r, false);
|
||||
}
|
||||
|
||||
private void doTrials(int n, int min, int max, Random r, boolean caseSensitive) throws CoreException {
|
||||
|
|
|
@ -133,7 +133,7 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
|
|||
@Override
|
||||
public boolean visitValue(char[] macro, char[] value) {
|
||||
PreprocessorMacro m = fMacroDictionary.get(macro);
|
||||
return m != null && CharArrayUtils.equals(m.getExpansion(), value);
|
||||
return m != null && CharArrayUtils.equals(SignificantMacros.shortenValue(m.getExpansion()), value);
|
||||
}
|
||||
|
||||
private boolean isDefined(char[] macro) {
|
||||
|
@ -246,7 +246,6 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
|
|||
private final LocationMap fLocationMap;
|
||||
private CharArraySet fPreventInclusion= new CharArraySet(0);
|
||||
|
||||
private final Lexer fRootLexer;
|
||||
private final ScannerContext fRootContext;
|
||||
protected ScannerContext fCurrentContext;
|
||||
|
||||
|
@ -302,8 +301,8 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
|
|||
setupMacroDictionary(configuration, info, language);
|
||||
|
||||
ILocationCtx ctx= fLocationMap.pushTranslationUnit(filePath, fRootContent.getSource());
|
||||
fRootLexer= new Lexer(fRootContent.getSource(), fLexOptions, this, this);
|
||||
fRootContext= fCurrentContext= new ScannerContext(ctx, null, fRootLexer);
|
||||
Lexer lexer = new Lexer(fRootContent.getSource(), fLexOptions, this, this);
|
||||
fRootContext= fCurrentContext= new ScannerContext(ctx, null, lexer);
|
||||
if (info instanceof IExtendedScannerInfo) {
|
||||
final IExtendedScannerInfo einfo= (IExtendedScannerInfo) info;
|
||||
fPreIncludedFiles= new String[][] { einfo.getMacroFiles(), einfo.getIncludeFiles() };
|
||||
|
@ -346,11 +345,11 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
|
|||
@Override
|
||||
public void setContentAssistMode(int offset) {
|
||||
fContentAssistLimit= offset;
|
||||
fRootLexer.setContentAssistMode(offset);
|
||||
fRootContext.getLexer().setContentAssistMode(offset);
|
||||
}
|
||||
|
||||
public boolean isContentAssistMode() {
|
||||
return fRootLexer.isContentAssistMode();
|
||||
return fRootContext.getLexer().isContentAssistMode();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -469,7 +468,7 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
|
|||
InternalFileContent content= fFileContentProvider.getContentForContextToHeaderGap(location,
|
||||
fMacroDictionaryFacade);
|
||||
if (content != null && content.getKind() == InclusionKind.FOUND_IN_INDEX) {
|
||||
processInclusionFromIndex(0, location, content, false);
|
||||
processInclusionFromIndex(0, content, false);
|
||||
}
|
||||
|
||||
detectIncludeGuard(location, fRootContent.getSource(), fRootContext);
|
||||
|
@ -577,7 +576,7 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
|
|||
}
|
||||
|
||||
try {
|
||||
t= internalFetchToken(fRootContext, CHECK_NUMBERS, false);
|
||||
t= internalFetchToken(fRootContext, CHECK_NUMBERS | REPORT_SIGNIFICANT_MACROS | IGNORE_UNDEFINED_SIGNIFICANT_MACROS, false);
|
||||
} catch (OffsetLimitReachedException e) {
|
||||
fHandledCompletion= true;
|
||||
throw e;
|
||||
|
@ -1463,7 +1462,7 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
|
|||
} catch (CoreException e) {
|
||||
}
|
||||
|
||||
processInclusionFromIndex(poundOffset, path, fi, true);
|
||||
processInclusionFromIndex(poundOffset, fi, true);
|
||||
break;
|
||||
case USE_SOURCE:
|
||||
// Will be parsed
|
||||
|
@ -1502,7 +1501,7 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
|
|||
}
|
||||
}
|
||||
|
||||
private void processInclusionFromIndex(int offset, String path, InternalFileContent fi, boolean updateContext) {
|
||||
private void processInclusionFromIndex(int offset, InternalFileContent fi, boolean updateContext) {
|
||||
List<IIndexMacro> mdefs= fi.getMacroDefinitions();
|
||||
for (IIndexMacro macro : mdefs) {
|
||||
addMacroDefinition(macro);
|
||||
|
|
|
@ -337,7 +337,9 @@ final class ScannerContext {
|
|||
public void significantMacro(IMacroBinding macro) {
|
||||
final char[] macroName= macro.getNameCharArray();
|
||||
if (fInternalModifications != null && !fInternalModifications.containsKey(macroName)) {
|
||||
fSignificantMacros.put(macroName, macro.getExpansion());
|
||||
final char[] expansion = macro.getExpansion();
|
||||
if (expansion != null)
|
||||
fSignificantMacros.put(macroName, SignificantMacros.shortenValue(expansion));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -398,18 +400,21 @@ final class ScannerContext {
|
|||
return;
|
||||
|
||||
sm.accept(new ISignificantMacros.IVisitor() {
|
||||
@Override
|
||||
public boolean visitValue(char[] macro, char[] value) {
|
||||
if (!fInternalModifications.containsKey(macro)) {
|
||||
fSignificantMacros.put(macro, value);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public boolean visitUndefined(char[] macro) {
|
||||
if (!fInternalModifications.containsKey(macro)) {
|
||||
fSignificantMacros.put(macro, SignificantMacros.UNDEFINED);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public boolean visitDefined(char[] macro) {
|
||||
if (!fInternalModifications.containsKey(macro)) {
|
||||
fSignificantMacros.put(macro, SignificantMacros.DEFINED);
|
||||
|
|
|
@ -28,11 +28,10 @@ import org.eclipse.cdt.core.parser.util.CharArrayUtils;
|
|||
* A <code>null</code> string is encoded as a single comma.
|
||||
*/
|
||||
public class SignificantMacros implements ISignificantMacros {
|
||||
public static final char[] UNDEFINED = {};
|
||||
public static final char[] DEFINED = {};
|
||||
private static final int ENCODED_UNDEFINED = Character.MAX_VALUE;
|
||||
private static final int ENCODED_DEFINED = Character.MAX_VALUE-1;
|
||||
public static final char[] DEFINED = {0};
|
||||
public static final char[] UNDEFINED = {1};
|
||||
private static final Comparator<Object> SORTER = new Comparator<Object>() {
|
||||
@Override
|
||||
public int compare(Object o1, Object o2) {
|
||||
return CharArrayUtils.compare((char[])o1, (char[])o2);
|
||||
}
|
||||
|
@ -58,13 +57,7 @@ public class SignificantMacros implements ISignificantMacros {
|
|||
char[] name= (char[]) key;
|
||||
char[] value= sigMacros.get(name);
|
||||
buffer.append((char) name.length).append(name);
|
||||
if (value == DEFINED) {
|
||||
buffer.append((char) ENCODED_DEFINED);
|
||||
} else if (value == UNDEFINED) {
|
||||
buffer.append((char) ENCODED_UNDEFINED);
|
||||
} else {
|
||||
buffer.append((char) value.length).append(value);
|
||||
}
|
||||
buffer.append((char) value.length).append(value);
|
||||
}
|
||||
int len= buffer.length();
|
||||
char[] result= new char[len];
|
||||
|
@ -93,6 +86,7 @@ public class SignificantMacros implements ISignificantMacros {
|
|||
&& CharArrayUtils.equals(fEncoded, ((SignificantMacros) obj).fEncoded);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept(IVisitor visitor) {
|
||||
final char[] encoded = fEncoded;
|
||||
final int len = encoded.length;
|
||||
|
@ -102,28 +96,27 @@ public class SignificantMacros implements ISignificantMacros {
|
|||
int v= i + len1;
|
||||
if (v >= len)
|
||||
break;
|
||||
final int len2 = encoded[v++];
|
||||
if (v+len2 > len)
|
||||
break;
|
||||
|
||||
char[] macro= extract(encoded, i, len1);
|
||||
final int len2 = encoded[v++];
|
||||
switch(len2) {
|
||||
case ENCODED_UNDEFINED:
|
||||
i= v;
|
||||
if (!visitor.visitUndefined(macro))
|
||||
return false;
|
||||
break;
|
||||
case ENCODED_DEFINED:
|
||||
i= v;
|
||||
if (!visitor.visitDefined(macro))
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
i= v+len2;
|
||||
if (i > len)
|
||||
break;
|
||||
if (!visitor.visitValue(macro, extract(encoded, v, len2)))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
i= v+len2;
|
||||
if (len2 == 1) {
|
||||
if (encoded[v] == UNDEFINED[0]) {
|
||||
if (!visitor.visitUndefined(macro))
|
||||
return false;
|
||||
continue;
|
||||
}
|
||||
if (encoded[v] == DEFINED[0]) {
|
||||
if (!visitor.visitDefined(macro))
|
||||
return false;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
final char[] value = extract(encoded, v, len2);
|
||||
if (!visitor.visitValue(macro, value))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -134,6 +127,7 @@ public class SignificantMacros implements ISignificantMacros {
|
|||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public char[] encode() {
|
||||
return fEncoded;
|
||||
}
|
||||
|
@ -147,14 +141,17 @@ public class SignificantMacros implements ISignificantMacros {
|
|||
final StringBuilder buf= new StringBuilder();
|
||||
buf.append('{');
|
||||
accept(new IVisitor() {
|
||||
@Override
|
||||
public boolean visitValue(char[] macro, char[] value) {
|
||||
buf.append(macro).append('=').append(value).append(',');
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public boolean visitUndefined(char[] macro) {
|
||||
buf.append(macro).append('=').append("null,");
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public boolean visitDefined(char[] macro) {
|
||||
buf.append(macro).append('=').append("*,");
|
||||
return true;
|
||||
|
@ -166,4 +163,19 @@ public class SignificantMacros implements ISignificantMacros {
|
|||
buf.append('}');
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
public static char[] shortenValue(char[] expansion) {
|
||||
if (expansion.length <= 16)
|
||||
return expansion;
|
||||
char[] result= new char[16];
|
||||
System.arraycopy(expansion, 0, result, 0, 8);
|
||||
StreamHasher hasher= new StreamHasher();
|
||||
hasher.addChunk(expansion);
|
||||
long hash= hasher.computeHash();
|
||||
for(int i= 0; i<8; i++) {
|
||||
result[8+i]= (char) (hash & 0xff);
|
||||
hash= hash >> 1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -212,10 +212,11 @@ public class PDOM extends PlatformObject implements IPDOM {
|
|||
* 120.0 - Enumerators in global index, bug 356235
|
||||
* 120.1 - Specializations of using declarations, bug 357293.
|
||||
* 121.0 - Multiple variants of included header file, bug 197989.
|
||||
* 122.0 - Compacting strings
|
||||
*/
|
||||
private static final int MIN_SUPPORTED_VERSION= version(121, 0);
|
||||
private static final int MAX_SUPPORTED_VERSION= version(121, Short.MAX_VALUE);
|
||||
private static final int DEFAULT_VERSION = version(121, 0);
|
||||
private static final int MIN_SUPPORTED_VERSION= version(122, 0);
|
||||
private static final int MAX_SUPPORTED_VERSION= version(122, Short.MAX_VALUE);
|
||||
private static final int DEFAULT_VERSION = version(122, 0);
|
||||
|
||||
private static int version(int major, int minor) {
|
||||
return (major << 16) + minor;
|
||||
|
|
|
@ -252,17 +252,47 @@ final class Chunk {
|
|||
fBuffer[++idx]= (byte)(value);
|
||||
}
|
||||
|
||||
public void putChars(final long offset, char[] chars, int start, int len) {
|
||||
assert fLocked;
|
||||
fDirty= true;
|
||||
int idx= recPtrToIndex(offset)-1;
|
||||
final int end= start+len;
|
||||
for (int i = start; i < end; i++) {
|
||||
char value= chars[i];
|
||||
fBuffer[++idx]= (byte)(value >> 8);
|
||||
fBuffer[++idx]= (byte)(value);
|
||||
}
|
||||
}
|
||||
|
||||
public void putCharsAsBytes(final long offset, char[] chars, int start, int len) {
|
||||
assert fLocked;
|
||||
fDirty= true;
|
||||
int idx= recPtrToIndex(offset)-1;
|
||||
final int end= start+len;
|
||||
for (int i = start; i < end; i++) {
|
||||
char value= chars[i];
|
||||
fBuffer[++idx]= (byte)(value);
|
||||
}
|
||||
}
|
||||
|
||||
public char getChar(final long offset) {
|
||||
int idx= recPtrToIndex( offset );
|
||||
return (char) (((fBuffer[idx] << 8) | (fBuffer[++idx] & 0xff)));
|
||||
}
|
||||
|
||||
public void getCharArray(final long offset, final char[] result) {
|
||||
public void getChars(final long offset, final char[] result, int start, int len) {
|
||||
final ByteBuffer buf= ByteBuffer.wrap(fBuffer);
|
||||
buf.position(recPtrToIndex( offset ));
|
||||
buf.asCharBuffer().get(result);
|
||||
buf.asCharBuffer().get(result, start, len);
|
||||
}
|
||||
|
||||
|
||||
public void getCharsFromBytes(final long offset, final char[] result, int start, int len) {
|
||||
final int pos = recPtrToIndex(offset);
|
||||
for (int i = 0; i < len; i++) {
|
||||
result[start+i] = (char) (fBuffer[pos+i] & 0xff);
|
||||
}
|
||||
}
|
||||
|
||||
void clear(final long offset, final int length) {
|
||||
assert fLocked;
|
||||
fDirty= true;
|
||||
|
|
|
@ -530,25 +530,42 @@ public class Database {
|
|||
}
|
||||
|
||||
public IString newString(String string) throws CoreException {
|
||||
if (string.length() > ShortString.MAX_LENGTH)
|
||||
return new LongString(this, string);
|
||||
else
|
||||
return new ShortString(this, string);
|
||||
return newString(string.toCharArray());
|
||||
}
|
||||
|
||||
public IString newString(char[] chars) throws CoreException {
|
||||
if (chars.length > ShortString.MAX_LENGTH)
|
||||
return new LongString(this, chars);
|
||||
int len= chars.length;
|
||||
int bytelen;
|
||||
final boolean useBytes = useBytes(chars);
|
||||
if (useBytes) {
|
||||
bytelen= len;
|
||||
} else {
|
||||
bytelen= 2*len;
|
||||
}
|
||||
|
||||
if (bytelen > ShortString.MAX_BYTE_LENGTH)
|
||||
return new LongString(this, chars, useBytes);
|
||||
else
|
||||
return new ShortString(this, chars);
|
||||
return new ShortString(this, chars, useBytes);
|
||||
}
|
||||
|
||||
private boolean useBytes(char[] chars) {
|
||||
for (char c : chars) {
|
||||
if ((c & 0xff00) != 0)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public IString getString(long offset) throws CoreException {
|
||||
int length = getInt(offset);
|
||||
if (length > ShortString.MAX_LENGTH)
|
||||
final int l = getInt(offset);
|
||||
int bytelen= l<0 ? -l : 2*l;
|
||||
if (bytelen > ShortString.MAX_BYTE_LENGTH) {
|
||||
return new LongString(this, offset);
|
||||
else
|
||||
return new ShortString(this, offset);
|
||||
}
|
||||
return new ShortString(this, offset);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -13,8 +13,6 @@
|
|||
|
||||
package org.eclipse.cdt.internal.core.pdom.db;
|
||||
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
import org.eclipse.cdt.core.CCorePlugin;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
|
||||
|
@ -48,73 +46,117 @@ public class LongString implements IString {
|
|||
this.record = record;
|
||||
}
|
||||
|
||||
private interface IWriter {
|
||||
public void writeChars(int start, int length, long p) throws CoreException;
|
||||
}
|
||||
public LongString(Database db, final char[] chars, boolean useBytes) throws CoreException {
|
||||
final int numChars1 = useBytes ? NUM_CHARS1*2 : NUM_CHARS1;
|
||||
final int numCharsn = useBytes ? NUM_CHARSN*2 : NUM_CHARSN;
|
||||
|
||||
private long createString(int length, IWriter writer) throws CoreException {
|
||||
// write the first record
|
||||
long firstRecord = db.malloc(Database.MAX_MALLOC_SIZE);
|
||||
int start = 0;
|
||||
db.putInt(firstRecord, length);
|
||||
writer.writeChars(start, NUM_CHARS1, firstRecord + CHARS1);
|
||||
this.db = db;
|
||||
this.record = db.malloc(Database.MAX_MALLOC_SIZE);
|
||||
|
||||
// Write the first record
|
||||
final int length = chars.length;
|
||||
db.putInt(this.record, useBytes ? -length : length);
|
||||
Chunk chunk= db.getChunk(this.record);
|
||||
|
||||
if (useBytes) {
|
||||
chunk.putCharsAsBytes(this.record + CHARS1, chars, 0, numChars1);
|
||||
} else {
|
||||
chunk.putChars(this.record + CHARS1, chars, 0, numChars1);
|
||||
}
|
||||
|
||||
// write the subsequent records
|
||||
long lastNext = firstRecord + NEXT1;
|
||||
start += NUM_CHARS1;
|
||||
while (length - start > NUM_CHARSN) {
|
||||
long lastNext = this.record + NEXT1;
|
||||
int start = numChars1;
|
||||
while (length-start > numCharsn) {
|
||||
long nextRecord = db.malloc(Database.MAX_MALLOC_SIZE);
|
||||
db.putRecPtr(lastNext, nextRecord);
|
||||
writer.writeChars(start, NUM_CHARSN, nextRecord + CHARSN);
|
||||
start += NUM_CHARSN;
|
||||
chunk= db.getChunk(nextRecord);
|
||||
if (useBytes) {
|
||||
chunk.putCharsAsBytes(nextRecord + CHARSN, chars, start, numCharsn);
|
||||
} else {
|
||||
chunk.putChars(nextRecord + CHARSN, chars, start, numCharsn);
|
||||
}
|
||||
start += numCharsn;
|
||||
lastNext = nextRecord + NEXTN;
|
||||
}
|
||||
|
||||
// Write the final record
|
||||
length -= start;
|
||||
long finalRecord = db.malloc(CHARSN + (length) * 2);
|
||||
db.putRecPtr(lastNext, finalRecord);
|
||||
writer.writeChars(start, length, finalRecord + CHARSN);
|
||||
|
||||
return firstRecord;
|
||||
}
|
||||
|
||||
public LongString(Database db, final String string) throws CoreException {
|
||||
this.db = db;
|
||||
this.record = createString(string.length(), new IWriter() {
|
||||
public void writeChars(int start, int length, long p) throws CoreException {
|
||||
for (int i = start; i < start + length; ++i) {
|
||||
LongString.this.db.putChar(p, string.charAt(i));
|
||||
p += 2;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public LongString(Database db, final char[] chars) throws CoreException {
|
||||
this.db = db;
|
||||
this.record = createString(chars.length, new IWriter() {
|
||||
public void writeChars(int start, int length, long p) throws CoreException {
|
||||
for (int i = start; i < start + length; ++i) {
|
||||
LongString.this.db.putChar(p, chars[i]);
|
||||
p += 2;
|
||||
}
|
||||
}
|
||||
});
|
||||
// Write last record
|
||||
int remaining= length - start;
|
||||
long nextRecord = db.malloc(CHARSN + (useBytes ? remaining : remaining*2));
|
||||
db.putRecPtr(lastNext, nextRecord);
|
||||
chunk= db.getChunk(nextRecord);
|
||||
if (useBytes) {
|
||||
chunk.putCharsAsBytes(nextRecord + CHARSN, chars, start, remaining);
|
||||
} else {
|
||||
chunk.putChars(nextRecord + CHARSN, chars, start, remaining);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getRecord() {
|
||||
return record;
|
||||
}
|
||||
|
||||
@Override
|
||||
public char[] getChars() throws CoreException {
|
||||
int length = db.getInt(record + LENGTH);
|
||||
final boolean useBytes = length < 0;
|
||||
int numChars1 = NUM_CHARS1;
|
||||
int numCharsn = NUM_CHARSN;
|
||||
if (useBytes) {
|
||||
length= -length;
|
||||
numChars1 *= 2;
|
||||
numCharsn *= 2;
|
||||
}
|
||||
|
||||
final char[] chars = new char[length];
|
||||
|
||||
// First record
|
||||
long p = record;
|
||||
Chunk chunk= db.getChunk(p);
|
||||
if (useBytes) {
|
||||
chunk.getCharsFromBytes(p+CHARS1, chars, 0, numChars1);
|
||||
} else {
|
||||
chunk.getChars(p+CHARS1, chars, 0, numChars1);
|
||||
}
|
||||
|
||||
int start= numChars1;
|
||||
p= record + NEXT1;
|
||||
|
||||
// Other records
|
||||
while (start < length) {
|
||||
p = db.getRecPtr(p);
|
||||
int partLen= Math.min(length-start, numCharsn);
|
||||
chunk= db.getChunk(p);
|
||||
if (useBytes) {
|
||||
chunk.getCharsFromBytes(p+CHARSN, chars, start, partLen);
|
||||
} else {
|
||||
chunk.getChars(p+CHARSN, chars, start, partLen);
|
||||
}
|
||||
start+= partLen;
|
||||
p=p+NEXTN;
|
||||
}
|
||||
return chars;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete() throws CoreException {
|
||||
int length = db.getInt(record + LENGTH) - NUM_CHARS1;
|
||||
int length = db.getInt(record + LENGTH);
|
||||
final boolean useBytes = length < 0;
|
||||
int numChars1 = NUM_CHARS1;
|
||||
int numCharsn = NUM_CHARSN;
|
||||
if (useBytes) {
|
||||
length= -length;
|
||||
numChars1 *= 2;
|
||||
numCharsn *= 2;
|
||||
}
|
||||
long nextRecord = db.getRecPtr(record + NEXT1);
|
||||
db.free(record);
|
||||
length-= numChars1;
|
||||
|
||||
// Middle records
|
||||
while (length > NUM_CHARSN) {
|
||||
length -= NUM_CHARSN;
|
||||
while (length > numCharsn) {
|
||||
length -= numCharsn;
|
||||
long nextnext = db.getRecPtr(nextRecord + NEXTN);
|
||||
db.free(nextRecord);
|
||||
nextRecord = nextnext;
|
||||
|
@ -147,19 +189,6 @@ public class LongString implements IString {
|
|||
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()}
|
||||
*/
|
||||
|
@ -167,224 +196,53 @@ public class LongString implements IString {
|
|||
public int hashCode() {
|
||||
int h = hash;
|
||||
if (h == 0) {
|
||||
HashCodeComputer hcc;
|
||||
char chars[];
|
||||
try {
|
||||
int length = db.getInt(record + LENGTH);
|
||||
hcc = new HashCodeComputer();
|
||||
readChars(length, hcc);
|
||||
h= hcc.getHashcode();
|
||||
hash = h;
|
||||
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;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compare(IString string, boolean caseSensitive) throws CoreException {
|
||||
if (string instanceof LongString)
|
||||
return compare((LongString)string, caseSensitive);
|
||||
else if (string instanceof ShortString)
|
||||
return compare((ShortString)string, caseSensitive);
|
||||
else
|
||||
throw new IllegalArgumentException();
|
||||
return ShortString.compare(getChars(), string.getChars(), caseSensitive);
|
||||
}
|
||||
|
||||
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 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(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;
|
||||
}
|
||||
|
||||
@Override
|
||||
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;
|
||||
return ShortString.compare(getChars(), other.toCharArray(), caseSensitive);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (!i1.hasNext() && i2 != n2)
|
||||
return -1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
private interface IReader {
|
||||
public void appendChar(char c);
|
||||
@Override
|
||||
public int compare(char[] other, boolean caseSensitive) throws CoreException {
|
||||
return ShortString.compare(getChars(), other, caseSensitive);
|
||||
}
|
||||
|
||||
private void readChars(int length, IReader reader) throws CoreException {
|
||||
// First record
|
||||
long p = record + CHARS1;
|
||||
for (int i = 0; i < NUM_CHARS1; ++i) {
|
||||
reader.appendChar(db.getChar(p));
|
||||
p += 2;
|
||||
}
|
||||
length -= NUM_CHARS1;
|
||||
long nextRecord = db.getRecPtr(record + NEXT1);
|
||||
|
||||
// Middle records
|
||||
while (length > NUM_CHARSN) {
|
||||
p = nextRecord + CHARSN;
|
||||
for (int i = 0; i < NUM_CHARSN; ++i) {
|
||||
reader.appendChar(db.getChar(p));
|
||||
p += 2;
|
||||
}
|
||||
length -= NUM_CHARSN;
|
||||
nextRecord = db.getRecPtr(nextRecord + NEXTN);
|
||||
}
|
||||
|
||||
// Last record
|
||||
p = nextRecord + CHARSN;
|
||||
for (int i = 0; i < length; ++i) {
|
||||
reader.appendChar(db.getChar(p));
|
||||
p += 2;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience class for sequential access to LongString characters
|
||||
*/
|
||||
private class CharIterator {
|
||||
long p;
|
||||
int count;
|
||||
int length;
|
||||
|
||||
public CharIterator() throws CoreException {
|
||||
p = record + CHARS1;
|
||||
length = db.getInt(record + 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.getRecPtr(record + NEXT1) + CHARSN;
|
||||
}
|
||||
if(count > NUM_CHARS1 && ((count-NUM_CHARS1) % NUM_CHARSN)==0) {
|
||||
p = db.getRecPtr(p-(NUM_CHARSN*2)-4) + CHARSN;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean hasNext() {
|
||||
return count<length;
|
||||
}
|
||||
}
|
||||
|
||||
public char[] getChars() throws CoreException {
|
||||
int length = db.getInt(record + LENGTH);
|
||||
final char[] chars = new char[length];
|
||||
readChars(length, new IReader() {
|
||||
int cp = 0;
|
||||
public void appendChar(char c) {
|
||||
chars[cp++] = c;
|
||||
}
|
||||
});
|
||||
return chars;
|
||||
}
|
||||
|
||||
public String getString() throws CoreException {
|
||||
int length = db.getInt(record + LENGTH);
|
||||
final StringBuilder buffer = new StringBuilder(length);
|
||||
readChars(length, new IReader() {
|
||||
public void appendChar(char c) {
|
||||
buffer.append(c);
|
||||
}
|
||||
});
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareCompatibleWithIgnoreCase(IString string) throws CoreException {
|
||||
int cmp= compare(string, false);
|
||||
return cmp==0 ? compare(string, true) : cmp;
|
||||
return ShortString.compareCompatibleWithIgnoreCase(getChars(), string.getChars());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int comparePrefix(char[] other, boolean caseSensitive) throws CoreException {
|
||||
return ShortString.comparePrefix(getChars(), other, caseSensitive);
|
||||
}
|
||||
|
||||
public int compareCompatibleWithIgnoreCase(char[] chars) throws CoreException {
|
||||
int cmp= compare(chars, false);
|
||||
return cmp==0 ? compare(chars, true) : cmp;
|
||||
|
||||
@Override
|
||||
public String getString() throws CoreException {
|
||||
return new String(getChars());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareCompatibleWithIgnoreCase(char[] other) throws CoreException {
|
||||
return ShortString.compareCompatibleWithIgnoreCase(getChars(), other);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2006, 2009 QNX Software Systems and others.
|
||||
* Copyright (c) 2006, 2011 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
|
||||
|
@ -13,6 +13,7 @@
|
|||
package org.eclipse.cdt.internal.core.pdom.db;
|
||||
|
||||
import org.eclipse.cdt.core.CCorePlugin;
|
||||
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
|
||||
/**
|
||||
|
@ -28,57 +29,53 @@ public class ShortString implements IString {
|
|||
private static final int LENGTH = 0;
|
||||
private static final int CHARS = 4;
|
||||
|
||||
public static final int MAX_LENGTH = (Database.MAX_MALLOC_SIZE - CHARS) / 2;
|
||||
public static final int MAX_BYTE_LENGTH = Database.MAX_MALLOC_SIZE - CHARS;
|
||||
|
||||
public ShortString(Database db, long offset) {
|
||||
this.db = db;
|
||||
this.record = offset;
|
||||
}
|
||||
|
||||
public ShortString(Database db, char[] chars) throws CoreException {
|
||||
public ShortString(Database db, char[] chars, boolean useBytes) throws CoreException {
|
||||
final int n = chars.length;
|
||||
this.db = db;
|
||||
this.record = db.malloc(CHARS + chars.length * 2);
|
||||
|
||||
this.record = db.malloc(CHARS + (useBytes ? n : 2*n));
|
||||
Chunk chunk = db.getChunk(record);
|
||||
chunk.putInt(record + LENGTH, (char)chars.length);
|
||||
int n = chars.length;
|
||||
chunk.putInt(record + LENGTH, useBytes ? -n : n);
|
||||
long p = record + CHARS;
|
||||
for (int i = 0; i < n; ++i) {
|
||||
chunk.putChar(p, chars[i]);
|
||||
p += 2;
|
||||
}
|
||||
}
|
||||
|
||||
public ShortString(Database db, String string) throws CoreException {
|
||||
this.db = db;
|
||||
this.record = db.malloc(CHARS + string.length() * 2);
|
||||
|
||||
Chunk chunk = db.getChunk(record);
|
||||
chunk.putInt(record + LENGTH, string.length());
|
||||
int n = string.length();
|
||||
long p = record + CHARS;
|
||||
for (int i = 0; i < n; ++i) {
|
||||
chunk.putChar(p, string.charAt(i));
|
||||
p += 2;
|
||||
if (useBytes) {
|
||||
chunk.putCharsAsBytes(p, chars, 0, n);
|
||||
} else {
|
||||
chunk.putChars(p, chars, 0, n);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getRecord() {
|
||||
return record;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete() throws CoreException {
|
||||
db.free(record);
|
||||
}
|
||||
|
||||
@Override
|
||||
public char[] getChars() throws CoreException {
|
||||
Chunk chunk = db.getChunk(record);
|
||||
int length = chunk.getInt(record + LENGTH);
|
||||
char[] chars = new char[length];
|
||||
chunk.getCharArray(record + CHARS, chars);
|
||||
final Chunk chunk = db.getChunk(record);
|
||||
final int l = chunk.getInt(record + LENGTH);
|
||||
final int length = Math.abs(l);
|
||||
final char[] chars = new char[length];
|
||||
if (l < 0) {
|
||||
chunk.getCharsFromBytes(record + CHARS, chars, 0, length);
|
||||
} else {
|
||||
chunk.getChars(record + CHARS, chars, 0, length);
|
||||
}
|
||||
return chars;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getString() throws CoreException {
|
||||
return new String(getChars());
|
||||
}
|
||||
|
@ -102,49 +99,22 @@ public class ShortString implements IString {
|
|||
if (n1 != n2)
|
||||
return false;
|
||||
|
||||
long p1 = record + CHARS;
|
||||
long p2 = string.record + CHARS;
|
||||
for (int i = 0; i < n1; ++i) {
|
||||
if (chunk1.getChar(p1) != chunk2.getChar(p2))
|
||||
return false;
|
||||
p1 += 2;
|
||||
p2 += 2;
|
||||
}
|
||||
return true;
|
||||
} else if (obj instanceof char[]) {
|
||||
return CharArrayUtils.equals(getChars(), string.getChars());
|
||||
}
|
||||
if (obj instanceof char[]) {
|
||||
char[] chars = (char[])obj;
|
||||
Chunk chunk = db.getChunk(record);
|
||||
|
||||
// Make sure size is the same
|
||||
int n = chunk.getInt(record);
|
||||
if (n != chars.length)
|
||||
if (getLength() != chars.length)
|
||||
return false;
|
||||
|
||||
// Check each character
|
||||
long p = record + CHARS;
|
||||
for (int i = 0; i < n; ++i) {
|
||||
if (chunk.getChar(p) != chars[i])
|
||||
return false;
|
||||
p += 2;
|
||||
}
|
||||
return true;
|
||||
return CharArrayUtils.equals(getChars(), chars);
|
||||
} else if (obj instanceof String) {
|
||||
String string = (String)obj;
|
||||
Chunk chunk = db.getChunk(record);
|
||||
|
||||
// Make sure size is the same
|
||||
int n = chunk.getInt(record);
|
||||
if (n != string.length())
|
||||
if (getLength() != string.length())
|
||||
return false;
|
||||
|
||||
// Check each character
|
||||
long p = record + CHARS;
|
||||
for (int i = 0; i < n; ++i) {
|
||||
if (chunk.getChar(p) != string.charAt(i))
|
||||
return false;
|
||||
p += 2;
|
||||
}
|
||||
return true;
|
||||
return CharArrayUtils.equals(getChars(), string.toCharArray());
|
||||
}
|
||||
} catch (CoreException e) {
|
||||
CCorePlugin.log(e);
|
||||
|
@ -173,112 +143,48 @@ public class ShortString implements IString {
|
|||
return h;
|
||||
}
|
||||
|
||||
public static int compare(final char[] chars, char[] other, boolean caseSensitive) {
|
||||
final int n = Math.min(chars.length, other.length);
|
||||
for (int i=0; i<n; i++) {
|
||||
int cmp= compareChars(chars[i], other[i], caseSensitive);
|
||||
if (cmp != 0)
|
||||
return cmp;
|
||||
}
|
||||
return chars.length - other.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compare(char[] other, boolean caseSensitive) throws CoreException {
|
||||
Chunk chunk = db.getChunk(record);
|
||||
|
||||
long i1 = record + CHARS;
|
||||
int i2 = 0;
|
||||
long 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;
|
||||
}
|
||||
|
||||
if (i1 == n1 && i2 != n2)
|
||||
return -1;
|
||||
else if (i2 == n2 && i1 != n1)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
return compare(getChars(), other, caseSensitive);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int compare(IString string, boolean caseSensitive) throws CoreException {
|
||||
if (string instanceof ShortString)
|
||||
return compare((ShortString)string, caseSensitive);
|
||||
else if (string instanceof LongString)
|
||||
return - ((LongString)string).compare(this, caseSensitive);
|
||||
else
|
||||
throw new IllegalArgumentException();
|
||||
return compare(getChars(), string.getChars(), caseSensitive);
|
||||
}
|
||||
|
||||
public int compare(ShortString other, boolean caseSensitive) throws CoreException {
|
||||
Chunk chunk1 = db.getChunk(record);
|
||||
Chunk chunk2 = other.db.getChunk(other.record);
|
||||
|
||||
long i1 = record + CHARS;
|
||||
long i2 = other.record + CHARS;
|
||||
long n1 = i1 + chunk1.getInt(record + LENGTH) * 2;
|
||||
long n2 = i2 + chunk2.getInt(other.record + LENGTH) * 2;
|
||||
|
||||
while (i1 < n1 && i2 < n2) {
|
||||
int cmp= compareChars(chunk1.getChar(i1), chunk2.getChar(i2), caseSensitive);
|
||||
if (cmp != 0)
|
||||
return cmp;
|
||||
|
||||
i1 += 2;
|
||||
i2 += 2;
|
||||
}
|
||||
|
||||
if (i1 == n1 && i2 != n2)
|
||||
return -1;
|
||||
else if (i2 == n2 && i1 != n1)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compare(String other, boolean caseSensitive) throws CoreException {
|
||||
Chunk chunk = db.getChunk(record);
|
||||
|
||||
long i1 = record + CHARS;
|
||||
int i2 = 0;
|
||||
long n1 = i1 + chunk.getInt(record + LENGTH) * 2;
|
||||
int n2 = other.length();
|
||||
|
||||
while (i1 < n1 && i2 < n2) {
|
||||
int cmp= compareChars(chunk.getChar(i1), other.charAt(i2), caseSensitive);
|
||||
if (cmp != 0)
|
||||
return cmp;
|
||||
|
||||
i1 += 2;
|
||||
++i2;
|
||||
}
|
||||
|
||||
if (i1 == n1 && i2 != n2)
|
||||
return -1;
|
||||
else if (i2 == n2 && i1 != n1)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
return compare(getChars(), other.toCharArray(), caseSensitive);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareCompatibleWithIgnoreCase(IString string) throws CoreException {
|
||||
if (string instanceof ShortString)
|
||||
return compareCompatibleWithIgnoreCase((ShortString)string);
|
||||
else if (string instanceof LongString)
|
||||
return - ((LongString)string).compareCompatibleWithIgnoreCase(this);
|
||||
else
|
||||
throw new IllegalArgumentException();
|
||||
return compareCompatibleWithIgnoreCase(string.getChars());
|
||||
}
|
||||
|
||||
public int compareCompatibleWithIgnoreCase(ShortString other) throws CoreException {
|
||||
Chunk chunk1 = db.getChunk(record);
|
||||
Chunk chunk2 = other.db.getChunk(other.record);
|
||||
@Override
|
||||
public int compareCompatibleWithIgnoreCase(char[] other) throws CoreException {
|
||||
return compareCompatibleWithIgnoreCase(getChars(), other);
|
||||
}
|
||||
|
||||
long i1 = record + CHARS;
|
||||
long i2 = other.record + CHARS;
|
||||
long n1 = i1 + chunk1.getInt(record + LENGTH) * 2;
|
||||
long n2 = i2 + chunk2.getInt(other.record + LENGTH) * 2;
|
||||
public static int compareCompatibleWithIgnoreCase(final char[] chars, char[] other) {
|
||||
final int n = Math.min(chars.length, other.length);
|
||||
int sensitiveCmp= 0;
|
||||
while (i1 < n1 && i2 < n2) {
|
||||
final char c1= chunk1.getChar(i1);
|
||||
final char c2= chunk2.getChar(i2);
|
||||
|
||||
for (int i=0; i<n; i++) {
|
||||
final char c1= chars[i];
|
||||
final char c2= other[i];
|
||||
if (c1 != c2) {
|
||||
int cmp= compareChars(c1, c2, false); // insensitive
|
||||
if (cmp != 0)
|
||||
|
@ -287,93 +193,40 @@ public class ShortString implements IString {
|
|||
if (sensitiveCmp == 0) {
|
||||
if (c1 < c2) {
|
||||
sensitiveCmp= -1;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
sensitiveCmp= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
i1 += 2;
|
||||
i2 += 2;
|
||||
}
|
||||
int cmp= chars.length - other.length;
|
||||
if (cmp != 0)
|
||||
return cmp;
|
||||
|
||||
if (i1 == n1 && i2 != n2)
|
||||
return -1;
|
||||
else if (i2 == n2 && i1 != n1)
|
||||
return 1;
|
||||
|
||||
return sensitiveCmp;
|
||||
}
|
||||
|
||||
public int compareCompatibleWithIgnoreCase(char[] chars) throws CoreException {
|
||||
Chunk chunk1 = db.getChunk(record);
|
||||
|
||||
long i1 = record + CHARS;
|
||||
int i2 = 0;
|
||||
long n1 = i1 + chunk1.getInt(record + LENGTH) * 2;
|
||||
int n2 = chars.length;
|
||||
int sensitiveCmp= 0;
|
||||
while (i1 < n1 && i2 < n2) {
|
||||
final char c1= chunk1.getChar(i1);
|
||||
final char c2= chars[i2];
|
||||
if (c1 != c2) {
|
||||
int cmp= compareChars(c1, c2, false); // insensitive
|
||||
if (cmp != 0)
|
||||
return cmp;
|
||||
|
||||
if (sensitiveCmp == 0) {
|
||||
if (c1 < c2) {
|
||||
sensitiveCmp= -1;
|
||||
}
|
||||
else {
|
||||
sensitiveCmp= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
i1 += 2;
|
||||
i2++;
|
||||
}
|
||||
|
||||
if (i1 == n1 && i2 != n2)
|
||||
return -1;
|
||||
else if (i2 == n2 && i1 != n1)
|
||||
return 1;
|
||||
|
||||
return sensitiveCmp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int comparePrefix(char[] other, boolean caseSensitive) throws CoreException {
|
||||
Chunk chunk = db.getChunk(record);
|
||||
return comparePrefix(getChars(), other, caseSensitive);
|
||||
}
|
||||
|
||||
public static int comparePrefix(final char[] chars, char[] other, boolean caseSensitive) {
|
||||
final int n = Math.min(chars.length, other.length);
|
||||
|
||||
long i1 = record + CHARS;
|
||||
int i2 = 0;
|
||||
long 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);
|
||||
for (int i=0; i<n; i++) {
|
||||
int cmp= compareChars(chars[i], other[i], caseSensitive);
|
||||
if (cmp != 0)
|
||||
return cmp;
|
||||
|
||||
i1 += 2;
|
||||
++i2;
|
||||
}
|
||||
|
||||
if (i1 == n1 && i2 != n2)
|
||||
if (chars.length < other.length)
|
||||
return -1;
|
||||
else
|
||||
return 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public char charAt(int i) throws CoreException {
|
||||
long ptr = record + CHARS + (i * 2);
|
||||
return db.getChar(ptr);
|
||||
}
|
||||
|
||||
public int getLength() throws CoreException {
|
||||
return db.getInt(record + LENGTH);
|
||||
public final int getLength() throws CoreException {
|
||||
return Math.abs(db.getInt(record + LENGTH));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Add table
Reference in a new issue