All Downloads are FREE. Search and download functionalities are using the official Maven repository.

wycc.io.HeapReader Maven / Gradle / Ivy

// Copyright 2011 The Whiley Project Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package wycc.io;

import java.io.*;

import wycc.util.Pair;
import wycc.lang.Syntactic;
import wycc.lang.Syntactic.Item;
import wycc.lang.Syntactic.Schema;


/**
 * 

* Responsible for writing a WyilFile to an output stream in binary form. The * binary format is structured to given maximum flexibility and to avoid * built-in limitations in terms of e.g. maximum sizes, etc. *

* * @author David J. Pearce * */ public abstract class HeapReader { protected final BinaryInputStream in; public HeapReader(InputStream output) { this.in = new BinaryInputStream(output); } public void close() throws IOException { in.close(); } public abstract Syntactic.Heap read() throws IOException; /** * Read all the items in this heap, returning the identified root item and an * array of all items contained therein. * * @return * @throws IOException */ protected Pair readItems() throws IOException { // first, write magic number Schema schema = checkHeader(); // second, determine number of items int size = in.read_uv(); // third, determine the root item int root = in.read_uv(); // Bytecode[] items = new Bytecode[size]; // third, read abstract syntactic items for (int i = 0; i != items.length; ++i) { items[i] = readItem(schema); } // return new Pair<>(root, constructItems(schema, items)); } /** * Check the header of this syntactic heap and, based on this, select the most * appropriate schema for decoding it. * * @return * @throws IOException */ protected abstract Schema checkHeader() throws IOException; protected Bytecode readItem(Schema schema) throws IOException { // read opcode int opcode = in.read_u8(); // Write operands int[] operands = readOperands(schema,opcode); // Write data (if any) byte[] data = readData(schema,opcode); // Pad to next byte boundary in.pad_u8(); // return new Bytecode(opcode,operands,data); } protected int[] readOperands(Schema schema, int opcode) throws IOException { // Determine operand layout Item.Operands layout = schema.getDescriptor(opcode).getOperandLayout(); int[] operands; int size; // Determine number of operands according to layout switch(layout) { case MANY: size = in.read_uv(); break; default: size = layout.ordinal(); } // operands = new int[size]; // Read operands for (int i = 0; i != operands.length; ++i) { operands[i] = in.read_uv(); } // return operands; } protected byte[] readData(Schema schema, int opcode) throws IOException { // Determine operand layout Item.Data layout = schema.getDescriptor(opcode).getDataLayout(); byte[] bytes; int size; // Determine number of bytes according to layout switch(layout) { case MANY: size = in.read_uv(); break; default: size = layout.ordinal(); } // bytes = new byte[size]; // Read operands for (int i = 0; i != bytes.length; ++i) { bytes[i] = (byte) in.read_u8(); } // return bytes; } protected Item[] constructItems(Schema schema, Bytecode[] bytecodes) { Item[] items = new Item[bytecodes.length]; // for(int i=0;i!=items.length;++i) { constructItem(i,schema,bytecodes,items); } // return items; } protected void constructItem(int index, Schema schema, Bytecode[] bytecodes, Item[] items) { // FIXME: this fails in the presence of truly recursive items. if (items[index] == null) { // This item not yet constructed, therefore construct it! Bytecode bytecode = bytecodes[index]; // Destructure bytecode int opcode = bytecode.opcode; int[] operands = bytecode.operands; byte[] data = bytecode.data; // Construct empty item Item item = schema.getDescriptor(bytecode.opcode).construct(opcode, new Item[operands.length], data); // Store item so can be accessed recursively items[index] = item; // Recursively construct operands for (int i = 0; i != operands.length; ++i) { constructItem(operands[i], schema, bytecodes, items); item.setOperand(i, items[operands[i]]); } } } private static class Bytecode { public final int opcode; public final int[] operands; public final byte[] data; public Bytecode(int opcode, int[] operands, byte[] data) { this.opcode = opcode; this.operands = operands; this.data = data; } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy