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

Improve performance of the IBinaryParser

by providing a new API
IBinaryParser.getBinary(byte[] hints, IPath path)
This commit is contained in:
Alain Magloire 2004-02-27 16:22:58 +00:00
parent d6a96dd12e
commit e138c8bc09
13 changed files with 136 additions and 63 deletions

View file

@ -1,3 +1,26 @@
2004-02-27 Alain Magloire
Performance improvement in the IBinaryParser and
changes in the API according to the specs.
Now we have:
IBinaryParser.getBinary(byte[] hints, IPath path);
This is important when having multiple parsers on
the same project. We provide a bucket/hints for the parser
to guess the type of file and reduce the number of open()s.
* model/org/eclipse/cdt/internal/core/model/CModelManager.java
* model/org/eclipse/cdt/internal/core/model/CProject.java
* model/org/eclipse/cdt/internal/core/model/NullBinaryParser.java
* src/org/eclipse/cdt/core/IBinaryParser.java
* utils/org/eclipse/cdt/utils/coff/Coff.java
* utils/org/eclipse/cdt/utils/coff/PE.java
* utils/org/eclipse/cdt/utils/coff/PEArchive.java
* utils/org/eclipse/cdt/utils/coff/parser/CygwinPEParser.java
* utils/org/eclipse/cdt/utils/coff/PEParser.java
* utils/org/eclipse/cdt/utils/elf/Elf.java
* utils/org/eclipse/cdt/utils/elf/parser/ElfParser.java
* utils/org/eclipse/cdt/utils/elf/parser/GNUElfParser.java
2004-02-26 Andrew Niefer
Mark strings that don't need to be externalized for translation

View file

@ -400,7 +400,7 @@ public class CModelManager implements IResourceChangeListener {
try {
IBinaryParser parser = getBinaryParser(file.getProject());
InputStream is = file.getContents();
byte[] bytes = new byte[128];
byte[] bytes = new byte[parser.getHintBufferSize()];
int count = is.read(bytes);
is.close();
if (count > 0 && count < bytes.length) {
@ -409,9 +409,7 @@ public class CModelManager implements IResourceChangeListener {
bytes = array;
}
IPath location = file.getLocation();
if (parser.isBinary(bytes, location)) {
return parser.getBinary(location);
}
return parser.getBinary(bytes, location);
} catch (IOException e) {
} catch (CoreException e) {
//e.printStackTrace();

View file

@ -121,7 +121,7 @@ public class CProject extends CContainer implements ICProject {
if (binParser != null) {
IBinaryFile bin;
try {
bin = binParser.getBinary(entry.getPath());
bin = binParser.getBinary(null, entry.getPath());
if (bin.getType() == IBinaryFile.ARCHIVE) {
lib = new LibraryReferenceArchive(cproject, entry, (IBinaryArchive)bin);
} else {

View file

@ -17,7 +17,7 @@ public class NullBinaryParser implements IBinaryParser {
/* (non-Javadoc)
* @see org.eclipse.cdt.core.IBinaryParser#getBinary(org.eclipse.core.runtime.IPath)
*/
public IBinaryFile getBinary(IPath path) throws IOException {
public IBinaryFile getBinary(byte[] data, IPath path) throws IOException {
throw new IOException(CCorePlugin.getResourceString("CoreModel.NullBinaryParser.Not_binary_file")); //$NON-NLS-1$
}
@ -35,4 +35,11 @@ public class NullBinaryParser implements IBinaryParser {
return false;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.IBinaryParser#getBufferSize()
*/
public int getHintBufferSize() {
return 0;
}
}

View file

@ -90,9 +90,33 @@ public interface IBinaryParser {
int getLineNumber(long offset);
}
IBinaryFile getBinary(IPath path) throws IOException;
/**
* Creates an IBinaryFile.
* @param hints - array byte that can be use to recognise the file.
* Can be null or empty array when no hints are passed.
* @param path
* @return
* @throws IOException
*/
IBinaryFile getBinary(byte[] hints, IPath path) throws IOException;
boolean isBinary(byte[] array, IPath path);
/**
* Returns the name of the Format.
* @return
*/
String getFormat();
/**
* True if the resource is a binary.
* @param hints
* @param path
* @return
*/
boolean isBinary(byte[] hints, IPath path);
/**
* Get a hint of the needed buffer size to recognise the file.
* @return
*/
int getHintBufferSize();
}

View file

@ -4,6 +4,7 @@
*/
package org.eclipse.cdt.utils.coff;
import java.io.EOFException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.text.DateFormat;
@ -54,7 +55,18 @@ public class Coff {
file.seek(offset);
byte[] hdr = new byte[FILHSZ];
file.readFully(hdr);
ReadMemoryAccess memory = new ReadMemoryAccess(hdr, true);
commonSetup(hdr, true);
}
public FileHeader (byte[] hdr, boolean little) throws EOFException {
commonSetup(hdr, little);
}
public void commonSetup(byte[] hdr, boolean little) throws EOFException {
if (hdr == null || hdr.length < FILHSZ) {
throw new EOFException("array to small"); //$NON-NLS-1
}
ReadMemoryAccess memory = new ReadMemoryAccess(hdr, little);
f_magic = memory.getUnsignedShort();
f_nscns = memory.getUnsignedShort();
f_timdat = memory.getInt();

View file

@ -66,7 +66,7 @@ public class PE {
Symbol[] symbolTable;
byte[] stringTable;
public class Attribute {
public static class Attribute {
public static final int PE_TYPE_EXE = 1;
public static final int PE_TYPE_SHLIB = 2;
public static final int PE_TYPE_OBJ = 3;
@ -342,10 +342,8 @@ public class PE {
}
}
public Attribute getAttribute() {
public static Attribute getAttributes(FileHeader filhdr) {
Attribute attrib = new Attribute();
FileHeader filhdr = getFileHeader();
// Machine type.
switch (filhdr.f_magic) {
case PEConstants.IMAGE_FILE_MACHINE_UNKNOWN:
@ -439,12 +437,25 @@ public class PE {
}
public static boolean isExeHeader(byte[] e_signature) {
if (e_signature.length < 2 || e_signature[0] != 'M' || e_signature[1] != 'Z')
if (e_signature == null || e_signature.length < 2 || e_signature[0] != 'M' || e_signature[1] != 'Z')
return false;
return true;
}
public static Attribute getAttributes(String file) throws IOException {
public Attribute getAttribute() throws IOException {
return getAttributes(getFileHeader());
}
public static Attribute getAttribute(byte[] data) throws IOException {
if (isExeHeader(data)) {
Coff.FileHeader filehdr;
filehdr = new Coff.FileHeader(data, true);
return getAttributes(filehdr);
}
throw new IOException("not a PE format");
}
public static Attribute getAttribute(String file) throws IOException {
PE pe = new PE(file);
Attribute attrib = pe.getAttribute();
pe.dispose();

View file

@ -201,7 +201,7 @@ public class PEArchive {
}
public static boolean isARHeader(byte[] ident) {
if (ident.length < 7
if (ident == null || ident.length < 7
|| ident[0] != '!'
|| ident[1] != '<'
|| ident[2] != 'a'

View file

@ -28,8 +28,8 @@ public class CygwinPEParser extends PEParser implements IBinaryParser, ICygwinTo
/**
* @see org.eclipse.cdt.core.model.IBinaryParser#getBinary(IPath)
*/
public IBinaryFile getBinary(IPath path) throws IOException {
IBinaryFile binary = super.getBinary(path);
public IBinaryFile getBinary(byte[] hints, IPath path) throws IOException {
IBinaryFile binary = super.getBinary(hints, path);
if (binary instanceof BinaryFile) {
((BinaryFile)binary).setToolsProvider(this);
}

View file

@ -11,6 +11,7 @@
package org.eclipse.cdt.utils.coff.parser;
import java.io.EOFException;
import java.io.IOException;
import org.eclipse.cdt.core.AbstractCExtension;
@ -28,14 +29,26 @@ public class PEParser extends AbstractCExtension implements IBinaryParser {
/**
* @see org.eclipse.cdt.core.model.IBinaryParser#getBinary(IFile)
*/
public IBinaryFile getBinary(IPath path) throws IOException {
public IBinaryFile getBinary(byte[] hints, IPath path) throws IOException {
if (path == null) {
throw new IOException("path is null");
}
BinaryFile binary = null;
try {
PE.Attribute attribute = PE.getAttributes(path.toOSString());
PE.Attribute attribute = null;
if (hints != null && hints.length > 0) {
try {
attribute = PE.getAttribute(hints);
} catch (EOFException e) {
// continue to try
}
}
// the hints may have to small, keep on trying.
if (attribute == null) {
attribute = PE.getAttribute(path.toOSString());
}
if (attribute != null) {
switch (attribute.getType()) {
case Attribute.PE_TYPE_EXE :
@ -105,4 +118,11 @@ public class PEParser extends AbstractCExtension implements IBinaryParser {
return isBin;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.IBinaryParser#getHintBufferSize()
*/
public int getHintBufferSize() {
return 128;
}
}

View file

@ -5,6 +5,7 @@ package org.eclipse.cdt.utils.elf;
* All Rights Reserved.
*/
import java.io.EOFException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
@ -143,7 +144,7 @@ public class Elf {
protected ELFhdr(byte [] bytes) throws IOException {
if(bytes.length <= e_ident.length) {
throw new IOException("Not ELF format");
throw new EOFException("Not ELF format");
}
System.arraycopy(bytes, 0, e_ident, 0, e_ident.length);
if ( e_ident[ELFhdr.EI_MAG0] != 0x7f || e_ident[ELFhdr.EI_MAG1] != 'E' ||

View file

@ -10,6 +10,7 @@
***********************************************************************/
package org.eclipse.cdt.utils.elf.parser;
import java.io.EOFException;
import java.io.IOException;
import org.eclipse.cdt.core.AbstractCExtension;
@ -22,11 +23,8 @@ import org.eclipse.core.runtime.IPath;
/**
*/
public class ElfParser extends AbstractCExtension implements IBinaryParser {
byte [] fCachedByteArray;
IPath fCachedPathEntry;
boolean fCachedIsAR;
public IBinaryFile getBinary(IPath path) throws IOException {
public IBinaryFile getBinary(byte[] hints, IPath path) throws IOException {
if (path == null) {
throw new IOException("path is null");
}
@ -34,25 +32,15 @@ public class ElfParser extends AbstractCExtension implements IBinaryParser {
BinaryFile binary = null;
try {
Elf.Attribute attribute = null;
//Try our luck with the cached entry first, then clear it
if(fCachedPathEntry != null && fCachedPathEntry.equals(path)) {
if (hints != null && hints.length > 0) {
try {
//Don't bother with ELF stuff if this is an archive
if(fCachedIsAR) {
return new BinaryArchive(path);
}
//Well, if it wasn't an archive, go for broke
attribute = Elf.getAttributes(fCachedByteArray);
} catch(Exception ex) {
attribute = null;
} finally {
fCachedPathEntry = null;
fCachedByteArray = null;
attribute = Elf.getAttributes(hints);
} catch (EOFException eof) {
// continue, the array was to small.
}
}
}
//Take a second run at it if the cache failed.
//Take a second run at it if the data array failed.
if(attribute == null) {
attribute = Elf.getAttributes(path.toOSString());
}
@ -95,24 +83,13 @@ public class ElfParser extends AbstractCExtension implements IBinaryParser {
* @see org.eclipse.cdt.core.IBinaryParser#isBinary(byte[], org.eclipse.core.runtime.IPath)
*/
public boolean isBinary(byte[] array, IPath path) {
boolean isBinaryReturnValue = false;
if(Elf.isElfHeader(array)) {
isBinaryReturnValue = true;
fCachedIsAR = false;
} else if(AR.isARHeader(array)) {
isBinaryReturnValue = true;
fCachedIsAR = true;
}
//If it is a binary, then cache the array in anticipation that we will be asked to do something with it
if(isBinaryReturnValue && array.length > 0) {
fCachedPathEntry = path;
fCachedByteArray = new byte[array.length];
System.arraycopy(array, 0, fCachedByteArray, 0, array.length);
}
return isBinaryReturnValue;
return Elf.isElfHeader(array) || AR.isARHeader(array);
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.IBinaryParser#getBufferSize()
*/
public int getHintBufferSize() {
return 128;
}
}

View file

@ -28,8 +28,8 @@ public class GNUElfParser extends ElfParser implements IBinaryParser, IToolsProv
/**
* @see org.eclipse.cdt.core.model.IBinaryParser#getBinary(IPath)
*/
public IBinaryFile getBinary(IPath path) throws IOException {
IBinaryFile binary = super.getBinary(path);
public IBinaryFile getBinary(byte[] data, IPath path) throws IOException {
IBinaryFile binary = super.getBinary(data, path);
if (binary instanceof BinaryFile) {
((BinaryFile)binary).setToolsProvider(this);
}