AS3 - Decimal number type support for ABC minor_version 17 or greater

This commit is contained in:
Jindra Petk
2011-07-12 09:44:42 +02:00
parent 07ca3fee80
commit 1f25be9236
10 changed files with 272 additions and 14 deletions

View File

@@ -50,10 +50,12 @@ public class ABC {
public long stringOffsets[];
public static String IDENT_STRING = " ";
public static final int MINORwithDECIMAL = 17;
public ABC(InputStream is) throws IOException {
ABCInputStream ais = new ABCInputStream(is);
major_version = ais.readU16();
minor_version = ais.readU16();
major_version = ais.readU16();
constants = new ConstantPool();
//constant integers
int constant_int_pool_count = ais.readU30();
@@ -76,6 +78,19 @@ public class ABC {
constants.constant_double[i] = ais.readDouble();
}
//constant decimal
if(minor_version >= MINORwithDECIMAL)
{
int constant_decimal_pool_count = ais.readU30();
constants.constant_decimal = new Decimal[constant_decimal_pool_count];
for (int i = 1; i < constant_decimal_pool_count; i++) { //index 0 not used. Values 1..n-1
constants.constant_decimal[i] = ais.readDecimal();
}
}else{
constants.constant_decimal=new Decimal[0];
}
//constant string
int constant_string_pool_count = ais.readU30();
constants.constant_string = new String[constant_string_pool_count];
@@ -202,8 +217,8 @@ public class ABC {
public void saveToStream(OutputStream os) throws IOException {
ABCOutputStream aos = new ABCOutputStream(os);
aos.writeU16(major_version);
aos.writeU16(minor_version);
aos.writeU16(major_version);
aos.writeU30(constants.constant_int.length);
for (int i = 1; i < constants.constant_int.length; i++) {
@@ -219,6 +234,13 @@ public class ABC {
aos.writeDouble(constants.constant_double[i]);
}
if(minor_version>=MINORwithDECIMAL){
aos.writeU30(constants.constant_decimal.length);
for (int i = 1; i < constants.constant_decimal.length; i++) {
aos.writeDecimal(constants.constant_decimal[i]);
}
}
aos.writeU30(constants.constant_string.length);
for (int i = 1; i < constants.constant_string.length; i++) {
aos.writeString(constants.constant_string[i]);

View File

@@ -313,6 +313,20 @@ public class ABCInputStream extends InputStream {
return traits;
}
public byte[] readBytes(int count) throws IOException{
byte ret[]=new byte[count];
for(int i=0;i<count;i++){
ret[i]=(byte)read();
}
return ret;
}
public Decimal readDecimal() throws IOException
{
byte data[]=readBytes(16);
return new Decimal(data);
}
public InstanceInfo readInstanceInfo() throws IOException {
InstanceInfo ret = new InstanceInfo();
ret.name_index = readU30();

View File

@@ -18,6 +18,7 @@
package com.jpexs.asdec.abc;
import com.jpexs.asdec.abc.types.Decimal;
import com.jpexs.asdec.abc.types.InstanceInfo;
import com.jpexs.asdec.abc.types.MethodInfo;
import com.jpexs.asdec.abc.types.Multiname;
@@ -273,4 +274,8 @@ public class ABCOutputStream extends OutputStream {
writeU30(ii.iinit_index);
writeTraits(ii.instance_traits);
}
public void writeDecimal(Decimal value) throws IOException{
write(value.data);
}
}

View File

@@ -84,11 +84,13 @@ public class AVM2Code {
public static final int DAT_INT_INDEX = OPT_U30 + 0x0E;
public static final int DAT_UINT_INDEX = OPT_U30 + 0x0F;
public static final int DAT_DOUBLE_INDEX = OPT_U30 + 0x10;
public static final int DAT_CASE_BASEOFFSET = OPT_S24 + 0x11;
public static final int DAT_DECIMAL_INDEX = OPT_U30 + 0x11;
public static final int DAT_CASE_BASEOFFSET = OPT_S24 + 0x12;
public static InstructionDefinition instructionSet[] = new InstructionDefinition[]{
new AddIns(),
new InstructionDefinition(0x9b,"add_d",new int[]{}),
new AddIIns(),
new InstructionDefinition(0xb5,"add_p",new int[]{AVM2Code.OPT_U30}),
new ApplyTypeIns(),
new AsTypeIns(),
new AsTypeLateIns(),
@@ -127,6 +129,8 @@ public class AVM2Code {
new ConvertOIns(),
new ConvertUIns(),
new ConvertSIns(),
new InstructionDefinition(0x79,"convert_m",new int[]{}),
new InstructionDefinition(0x7a,"convert_m_p",new int[]{AVM2Code.OPT_U30 /*param (?)*/}),
new DebugIns(),
new DebugFileIns(),
new DebugLineIns(),
@@ -134,9 +138,11 @@ public class AVM2Code {
new DecLocalIIns(),
new DecrementIns(),
new DecrementIIns(),
new InstructionDefinition(0x5b,"deldescendants",new int[]{}),
new DeletePropertyIns(),
new InstructionDefinition(0x6b,"deletepropertylate",new int[]{}),
new DivideIns(),
new InstructionDefinition(0xb8,"divide_p",new int[]{AVM2Code.OPT_U30}),
new DupIns(),
new DXNSIns(),
new DXNSLateIns(),
@@ -185,6 +191,10 @@ public class AVM2Code {
new IncLocalIIns(),
new IncrementIns(),
new IncrementIIns(),
new InstructionDefinition(0x9c,"increment_p",new int[]{AVM2Code.OPT_U30 /*param*/}),
new InstructionDefinition(0x9d,"inclocal_p",new int[]{AVM2Code.OPT_U30 /*param*/,AVM2Code.DAT_REGISTER_INDEX}),
new InstructionDefinition(0x9e,"decrement_p",new int[]{AVM2Code.OPT_U30 /*param*/}),
new InstructionDefinition(0x9f,"declocal_p",new int[]{AVM2Code.OPT_U30 /*param*/,AVM2Code.DAT_REGISTER_INDEX}),
new InitPropertyIns(),
new InstanceOfIns(),
new IsTypeIns(),
@@ -197,10 +207,13 @@ public class AVM2Code {
new LookupSwitchIns(),
new LShiftIns(),
new ModuloIns(),
new InstructionDefinition(0xb9,"modulo_p",new int[]{AVM2Code.OPT_U30}),
new MultiplyIns(),
new MultiplyIIns(),
new InstructionDefinition(0xb7,"multiply_p",new int[]{AVM2Code.OPT_U30}),
new NegateIns(),
new NegateIIns(),
new InstructionDefinition(0x8f,"negate_p",new int[]{AVM2Code.OPT_U30 /* param */}),
new NewActivationIns(),
new NewArrayIns(),
new NewCatchIns(),
@@ -215,6 +228,8 @@ public class AVM2Code {
new PopScopeIns(),
new PushByteIns(),
new InstructionDefinition(0x22,"pushconstant",new int[]{AVM2Code.DAT_STRING_INDEX}),
new InstructionDefinition(0x33,"pushdecimal",new int[]{AVM2Code.DAT_DECIMAL_INDEX}),
new InstructionDefinition(0x34,"pushdnan",new int[]{}),
new PushDoubleIns(),
new PushFalseIns(),
new PushIntIns(),
@@ -244,8 +259,10 @@ public class AVM2Code {
new StrictEqualsIns(),
new SubtractIns(),
new SubtractIIns(),
new InstructionDefinition(0xb6,"subtract_p",new int[]{AVM2Code.OPT_U30}),
new SwapIns(),
new ThrowIns(),
new InstructionDefinition(0xf3,"timestamp",new int[]{}),
new TypeOfIns(),
new URShiftIns(),
new InstructionDefinition(0x35,"li8",new int[]{}),

View File

@@ -18,6 +18,7 @@
package com.jpexs.asdec.abc.avm2;
import com.jpexs.asdec.abc.types.Decimal;
import com.jpexs.asdec.abc.types.Multiname;
import com.jpexs.asdec.abc.types.Namespace;
import com.jpexs.asdec.abc.types.NamespaceSet;
@@ -31,6 +32,8 @@ public class ConstantPool {
public long constant_int[];
public long constant_uint[];
public double constant_double[];
/* Only for some minor versions */
public Decimal constant_decimal[];
public String constant_string[];
public Namespace constant_namespace[];
public NamespaceSet constant_namespace_set[];

View File

@@ -31,10 +31,11 @@ public class ConstantsListModel implements ListModel {
public static final int TYPE_UINT = 0;
public static final int TYPE_INT = 1;
public static final int TYPE_DOUBLE = 2;
public static final int TYPE_STRING = 3;
public static final int TYPE_NAMESPACE = 4;
public static final int TYPE_NAMESPACESET = 5;
public static final int TYPE_MULTINAME = 6;
public static final int TYPE_DECIMAL = 3;
public static final int TYPE_STRING = 4;
public static final int TYPE_NAMESPACE = 5;
public static final int TYPE_NAMESPACESET = 6;
public static final int TYPE_MULTINAME = 7;
private int type = TYPE_INT;
public ConstantsListModel(ConstantPool constants, int type) {
@@ -56,6 +57,8 @@ public class ConstantsListModel implements ListModel {
return makeUp(constants.constant_int.length - 1);
case TYPE_DOUBLE:
return makeUp(constants.constant_double.length - 1);
case TYPE_DECIMAL:
return makeUp(constants.constant_decimal.length - 1);
case TYPE_STRING:
return makeUp(constants.constant_string.length - 1);
case TYPE_NAMESPACE:
@@ -76,6 +79,8 @@ public class ConstantsListModel implements ListModel {
return "" + (index + 1) + ":" + constants.constant_int[index + 1];
case TYPE_DOUBLE:
return "" + (index + 1) + ":" + constants.constant_double[index + 1];
case TYPE_DECIMAL:
return "" + (index + 1) + ":" + constants.constant_decimal[index + 1];
case TYPE_STRING:
return "" + (index + 1) + ":" + Helper.escapeString(constants.constant_string[index + 1]);
case TYPE_NAMESPACE:

View File

@@ -133,15 +133,18 @@ public class MainFrame extends JFrame implements ActionListener, ItemListener {
autoResizeColWidth(constantTable, new DoubleTableModel(abc));
break;
case 3:
autoResizeColWidth(constantTable, new StringTableModel(abc));
autoResizeColWidth(constantTable, new DecimalTableModel(abc));
break;
case 4:
autoResizeColWidth(constantTable, new NamespaceTableModel(abc));
autoResizeColWidth(constantTable, new StringTableModel(abc));
break;
case 5:
autoResizeColWidth(constantTable, new NamespaceSetTableModel(abc));
autoResizeColWidth(constantTable, new NamespaceTableModel(abc));
break;
case 6:
autoResizeColWidth(constantTable, new NamespaceSetTableModel(abc));
break;
case 7:
autoResizeColWidth(constantTable, new MultinameTableModel(abc));
break;
}
@@ -285,7 +288,7 @@ public class MainFrame extends JFrame implements ActionListener, ItemListener {
/* Constants */
JPanel panConstants = new JPanel();
panConstants.setLayout(new BorderLayout());
constantTypeList = new JComboBox(new String[]{"UINT", "INT", "DOUBLE", "STRING", "NAMESPACE", "NAMESPACESET", "MULTINAME"});
constantTypeList = new JComboBox(new String[]{"UINT", "INT", "DOUBLE","DECIMAL", "STRING", "NAMESPACE", "NAMESPACESET", "MULTINAME"});
constantTable = new JTable();
autoResizeColWidth(constantTable, new UIntTableModel(abc));
constantTable.setAutoCreateRowSorter(true);
@@ -294,7 +297,7 @@ public class MainFrame extends JFrame implements ActionListener, ItemListener {
@Override
public void mouseClicked(MouseEvent e) {
if(e.getClickCount()==2){
if(constantTypeList.getSelectedIndex()==6){
if(constantTypeList.getSelectedIndex()==7){ //MULTINAME
int rowIndex=constantTable.getSelectedRow();
if(rowIndex==-1) return;
int multinameIndex=constantTable.convertRowIndexToModel(rowIndex);

View File

@@ -0,0 +1,147 @@
/*
* Copyright (C) 2010-2011 JPEXS
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package com.jpexs.asdec.abc.gui.tablemodels;
import com.jpexs.asdec.abc.ABC;
import javax.swing.event.TableModelListener;
import javax.swing.table.TableModel;
public class DecimalTableModel implements TableModel {
private ABC abc;
private static final String columnNames[] = new String[]{"Index", "Value"};
private static final Class classes[] = new Class[]{Long.class, String.class};
public DecimalTableModel(ABC abc) {
this.abc = abc;
}
/**
* Returns the number of rows in the model. A
* <code>JTable</code> uses this method to determine how many rows it
* should display. This method should be quick, as it
* is called frequently during rendering.
*
* @return the number of rows in the model
* @see #getColumnCount
*/
public int getRowCount() {
return abc.constants.constant_decimal.length;
}
/**
* Returns the number of columns in the model. A
* <code>JTable</code> uses this method to determine how many columns it
* should create and display by default.
*
* @return the number of columns in the model
* @see #getRowCount
*/
public int getColumnCount() {
return 2;
}
/**
* Returns the name of the column at <code>columnIndex</code>. This is used
* to initialize the table's column header name. Note: this name does
* not need to be unique; two columns in a table can have the same name.
*
* @param columnIndex the index of the column
* @return the name of the column
*/
public String getColumnName(int columnIndex) {
return columnNames[columnIndex];
}
/**
* Returns the most specific superclass for all the cell values
* in the column. This is used by the <code>JTable</code> to set up a
* default renderer and editor for the column.
*
* @param columnIndex the index of the column
* @return the common ancestor class of the object values in the model.
*/
public Class<?> getColumnClass(int columnIndex) {
return classes[columnIndex];
}
/**
* Returns true if the cell at <code>rowIndex</code> and
* <code>columnIndex</code>
* is editable. Otherwise, <code>setValueAt</code> on the cell will not
* change the value of that cell.
*
* @param rowIndex the row whose value to be queried
* @param columnIndex the column whose value to be queried
* @return true if the cell is editable
* @see #setValueAt
*/
public boolean isCellEditable(int rowIndex, int columnIndex) {
return false;
}
/**
* Returns the value for the cell at <code>columnIndex</code> and
* <code>rowIndex</code>.
*
* @param rowIndex the row whose value is to be queried
* @param columnIndex the column whose value is to be queried
* @return the value Object at the specified cell
*/
public Object getValueAt(int rowIndex, int columnIndex) {
if (columnIndex == 0) return rowIndex;
else {
return abc.constants.constant_decimal[rowIndex];
}
}
/**
* Sets the value in the cell at <code>columnIndex</code> and
* <code>rowIndex</code> to <code>aValue</code>.
*
* @param aValue the new value
* @param rowIndex the row whose value is to be changed
* @param columnIndex the column whose value is to be changed
* @see #getValueAt
* @see #isCellEditable
*/
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
}
/**
* Adds a listener to the list that is notified each time a change
* to the data model occurs.
*
* @param l the TableModelListener
*/
public void addTableModelListener(TableModelListener l) {
}
/**
* Removes a listener from the list that is notified each time a
* change to the data model occurs.
*
* @param l the TableModelListener
*/
public void removeTableModelListener(TableModelListener l) {
}
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright (C) 2011 JPEXS
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package com.jpexs.asdec.abc.types;
/**
*
* @author JPEXS
*/
public class Decimal {
public byte data[];
public Decimal(byte data[])
{
this.data=data;
}
@Override
public String toString() {
return new String(data);
}
}

View File

@@ -23,6 +23,7 @@ import com.jpexs.asdec.abc.avm2.ConstantPool;
public class ValueKind {
public static final int CONSTANT_Decimal = 0x02; //decimal
public static final int CONSTANT_Int = 0x03;// integer
public static final int CONSTANT_UInt = 0x04;// uinteger
public static final int CONSTANT_Double = 0x06;// double
@@ -38,8 +39,8 @@ public class ValueKind {
public static final int CONSTANT_ExplicitNamespace = 0x19;// Namespace
public static final int CONSTANT_StaticProtectedNs = 0x1A;// Namespace
public static final int CONSTANT_PrivateNs = 0x05;// namespace
private static final int optionalKinds[] = new int[]{0x03, 0x04, 0x06, 0x01, 0x0B, 0x0A, 0x0C, 0x00, 0x08, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x05};
private static final String optionalKindNames[] = new String[]{"Int", "UInt", "Double", "Utf8", "True", "False", "Null", "Undefined", "Namespace", "PackageNamespace", "PackageInternalNs", "ProtectedNamespace", "ExplicitNamespace", "StaticProtectedNs", "PrivateNs"};
private static final int optionalKinds[] = new int[]{0x03, 0x04, 0x06,0x02, 0x01, 0x0B, 0x0A, 0x0C, 0x00, 0x08, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x05};
private static final String optionalKindNames[] = new String[]{"Int", "UInt", "Double","Decimal", "Utf8", "True", "False", "Null", "Undefined", "Namespace", "PackageNamespace", "PackageInternalNs", "ProtectedNamespace", "ExplicitNamespace", "StaticProtectedNs", "PrivateNs"};
public int value_index;
public int value_kind;
@@ -78,6 +79,9 @@ public class ValueKind {
case CONSTANT_Double:
ret = "" + constants.constant_double[value_index];
break;
case CONSTANT_Decimal:
ret = "" + constants.constant_decimal[value_index];
break;
case CONSTANT_Utf8:
ret = "\"" + constants.constant_string[value_index] + "\"";
break;