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:
parent
d6a96dd12e
commit
e138c8bc09
13 changed files with 136 additions and 63 deletions
|
@ -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
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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' ||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue