Up ] main() ]

Parser
Home News Listen Read Resources Feedback Contents Search RSS, Contacts

 

 

 

Sponsor Links

Fast, reliable data access for ODBC, JDBC, ADO.NET and XML
Need an expert for Java, XML and Web Services projects?
WSSC 2008: The only event dedicated to Web Services Security technology and business
IBM MQSeries for Compaq NSK - ( v. 5.1 ) - media
88x31 CTIX Logo - Clear Background
Microsoft SQL Server 2005 Standard Edition X64 - complete package
Corel DESIGNER Technical Suite - ( v. 12 ) - complete package
Find XML examples at XML Pitstop

 

Madhu's Workshop

Reflecting on Binary Files

XML
BCEL
XML Spy

Compiler
ANTLR

Java
VM

Tools
Apache
Eclipse

Logo for grid computing portal: GridSummit.com
Logo for database portal logo: SQLSummit.com

 

<< Previous 1 2 3 4 5

Notice the type byte is not included here. That's read by the parser to determine which subclass to use. We really don't need it once the subclass instances are created because the subclass objects know their own type.

The following is the complete parser that handles primitives and aggregate types:

/**
 * Created on Oct 8, 2005 5:03:27 PM
 *
 * @author Madhu Siddalingaiah
 * http://www.madhu.com
 */
package com.madhu.picovm;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.Comparator;

public class Parser {
    private InputStream in;
    private int count;
    private Comparator fieldComparator;

    public Parser() {
    }

    public Object parse(InputStream in, Class clazz) throws Exception {
        this.in = in;
        fieldComparator = new FieldComparator();
        return parse(clazz);
    }

    public Object parse(Class clazz) throws Exception {
        if (clazz.isPrimitive()) {
            if (clazz == Byte.TYPE) {
                return new Byte((byte) readBytes(1));
            } else if (clazz == Short.TYPE) {
                return new Short((short) readBytes(2));
            } else if (clazz == Integer.TYPE) {
                return new Integer((int) readBytes(4));
            } else if (clazz == Long.TYPE) {
                return new Long(readBytes(8));
            } else if (clazz == Float.TYPE) {
                return new Float(Float.intBitsToFloat((int) readBytes(4)));
            } else if (clazz == Double.TYPE) {
                return new Double(Double.longBitsToDouble(readBytes(8)));
            }
            throw new IllegalArgumentException("Unsupported primitive " + clazz);
        }
        if (clazz.isArray()) {
            String name = clazz.getName();
            String subtype = name.substring(2);
            Class aclass;
            switch (name.charAt(1)) {
                case 'Z': aclass = Boolean.TYPE; break;
                case 'B': aclass = Byte.TYPE; break;
                case 'S': aclass = Short.TYPE; break;
                case 'C': aclass = Character.TYPE; break;
                case 'I': aclass = Integer.TYPE; break;
                case 'J': aclass = Long.TYPE; break;
                case 'F': aclass = Float.TYPE; break;
                case 'D': aclass = Double.TYPE; break;
                case 'L': aclass = 
			Class.forName(subtype.substring(0, subtype.length()-1)); 
			break;
                default: throw new AssertionError("Unknown type: " + name);
            }
            int n = count;
            Object array = Array.newInstance(aclass, n);
            for (int i=0; i<n; i+=1) {
                Object value = parse(aclass);
                Array.set(array, i, value);
                // hack for constant pool
                if (value.getClass() == DoubleEntry.class ||
                    value.getClass() == LongEntry.class) {
                    i += 1;
                }
            }
            return array;
        }
        if (Modifier.isAbstract(clazz.getModifiers())) {
            Object[] subTypes = 
		(Object[]) clazz.getDeclaredField("SUBTYPES").get(null);
            Class typeClass = 
		(Class) clazz.getDeclaredField("TYPECLASS").get(null);
            Object type = parse(typeClass);
            for (int i=0; i<subTypes.length; i+=2) {
                if (type.equals(subTypes[i])) {
                    return parse((Class) subTypes[i+1]);
                }
            }
            throw new IllegalArgumentException("no match for subclass type " + type);
        }
        Field[] fields = clazz.getDeclaredFields();
        // field order is not guaranteed, so sort them by trailing number
        Arrays.sort(fields, fieldComparator);
        Object object = clazz.newInstance();
        for (int i = 0; i < fields.length; i++) {
            Field field = fields[i];
            field.set(object, parse(field.getType()));
            // hack for constant_pool_count
            if (field.getName().startsWith("constant_pool_count")) {
                count -= 1;
            }
        }
        return object;
    }

    class FieldComparator implements Comparator {
        /**
         * Order by trailing number in the field name
         * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
         */
        public int compare(Object o1, Object o2) {
            return getFieldNumber(o1) - getFieldNumber(o2);
        }

        private int getFieldNumber(Object o) {
            Field f = (Field) o;
            String name = f.getName();
            int us = name.lastIndexOf('_');
            return Integer.parseInt(name.substring(us+1));
        }
    }

    /**
     * @return a 64 bit value repesenting up to 8 bytes
     */
    private long readBytes(int size) throws IOException {
        long value = 0;
        for (int i=0; i<size; i+=1) {
            value <<= 8;
            value |= in.read();
        }
        count = (int) value;
        return value;
    }
}
 

Next: Grammar and main()


1 2 3 4 5 Next>>

 

 


 

Banner
BTS_Homepage
120x240

 

 

Home ] Up ] main() ]

Copyright © 2008,  Ken North Computing, LLC
Last modified: March 31, 2008