/// <summary> /// convert <see cref="SwfOp.ByteCode.Actions.ActionPushList">push list</see> to sequence of single <see cref="SwfOp.ByteCode.Actions.ActionPush" >push</see> actions /// </summary> private void ExplodePushLists(ArrayList actionRecord) { for (int i = 0; i < actionRecord.Count; i++) { BaseAction a = (BaseAction)actionRecord[i]; // check if action is multiple push ActionPushList pl = actionRecord[i] as ActionPushList; if (pl != null) { // resolve pushs to single push actions for (int j = 0; j < pl.Length; j++) { ActionPush p = pl[j]; actionRecord.Insert(i + 1 + j, p); } actionRecord.RemoveAt(i); } // process inner actionblocks if (a as ActionDefineFunction != null) { ActionDefineFunction f = (ActionDefineFunction)a; ExplodePushLists(f.ActionRecord); } if (a as ActionDefineFunction2 != null) { ActionDefineFunction2 f = (ActionDefineFunction2)a; ExplodePushLists(f.ActionRecord); } } }
public static void AreEqual(ActionPush expected, ActionPush actual, string message) { Assert.AreEqual(expected.Items.Count, actual.Items.Count, message + ".Items.Count"); for (var i = 0; i < expected.Items.Count; i++) { AreEqual(expected.Items[i], actual.Items[i], message + ".Actions[" + i + "]"); } }
/// <summary> /// Collaps sequence of single push actions into one multiple-push action /// </summary> private void CollapsPushActions(ArrayList actionRecord) { int i = 0; bool isPush; while (i < (actionRecord.Count - 1)) { isPush = actionRecord[i] is ActionPush; if (isPush) { int j = i; int count = 1; do { i++; if (i < actionRecord.Count) { isPush = (actionRecord[i] is ActionPush); if (isPush) { count++; } } } while ((isPush) && (i < actionRecord.Count)); if (count > 1) { ActionPush[] pushList = new ActionPush[count]; actionRecord.CopyTo(j, pushList, 0, count); actionRecord.RemoveRange(j, count); ActionPushList pl = new ActionPushList(pushList); actionRecord.Insert(j, pl); i = j + 1; } } else { // recursively step through functions inner actions ActionDefineFunction f = actionRecord[i] as ActionDefineFunction; if (f != null) { CollapsPushActions(f.ActionRecord); } // and function2 of course ActionDefineFunction2 f2 = actionRecord[i] as ActionDefineFunction2; if (f2 != null) { CollapsPushActions(f2.ActionRecord); } i++; } } }
XElement IActionVisitor <XElement, XElement> .Visit(ActionPush action, XElement param) { var xAction = new XElement("PushData"); var xItems = new XElement("items"); foreach (var item in action.Items) { switch (item.Type) { case ActionPushItemType.String: xItems.Add(new XElement("StackString", new XAttribute("value", item.String))); break; case ActionPushItemType.Float: xItems.Add(new XElement("StackFloat", new XAttribute("value", item.Float))); break; case ActionPushItemType.Null: xItems.Add(new XElement("StackNull")); break; case ActionPushItemType.Undefined: xItems.Add(new XElement("StackUndefined")); break; case ActionPushItemType.Register: xItems.Add(new XElement("StackRegister", new XAttribute("reg", item.Register))); break; case ActionPushItemType.Boolean: xItems.Add(new XElement("StackBoolean", new XAttribute("value", item.Boolean))); break; case ActionPushItemType.Double: xItems.Add(new XElement("StackDouble", new XAttribute("value", item.Double))); break; case ActionPushItemType.Integer: xItems.Add(new XElement("StackInteger", new XAttribute("value", item.Integer))); break; case ActionPushItemType.Constant8: xItems.Add(new XElement("StackDictionaryLookup", new XAttribute("index", item.Constant8))); break; case ActionPushItemType.Constant16: xItems.Add(new XElement("StackConstant16", new XAttribute("value", item.Constant16))); break; default: throw new NotSupportedException(); } } xAction.Add(xItems); return(xAction); }
/// <summary> /// Read multiply push action action as <see cref="SwfOp.ByteCode.Actions.ActionPushList">ActionPushList</see> from swf. /// </summary> private ActionPushList ReadActionPush(BinaryReader br) { // read block length int len = Convert.ToInt32(br.ReadUInt16()); int i = 0; ArrayList pushList = new ArrayList(); while (i < len) { int pushType = Convert.ToInt32(br.ReadByte()); i++; object val = new object(); switch (pushType) { case 0: string str = BinaryStringRW.ReadString(br); i += str.Length + 1; val = str; break; case 1: val = (object)br.ReadSingle(); i += 4; break; case 2: val = null; break; case 3: val = null; break; case 4: val = (object)Convert.ToInt32(br.ReadByte()); i++; break; case 5: val = (object )br.ReadBoolean(); i++; break; case 6: byte[] b0 = br.ReadBytes(4); byte[] b1 = br.ReadBytes(4); byte[] b = new byte[8]; b0.CopyTo(b, 4); b1.CopyTo(b, 0); val = (object)BitConverter.ToDouble(b, 0); i += 8; break; case 7: val = (object)br.ReadInt32(); i += 4; break; case 8: val = (object)Convert.ToInt32(br.ReadByte()); i++; break; case 9: val = (object)Convert.ToInt32(br.ReadUInt16()); i += 2; break; } ActionPush p = new ActionPush(pushType, val); pushList.Add(p); } ActionPush[] pList = new ActionPush[pushList.Count]; pushList.CopyTo(pList, 0); ActionPushList a = new ActionPushList(pList); //a.ByteSize = len+3; return(a); }
ActionBase IActionVisitor <XElement, ActionBase> .Visit(ActionPush action, XElement xAction) { var xItems = xAction.RequiredElement("items"); foreach (var xItem in xItems.Elements()) { switch (xItem.Name.LocalName) { case "StackString": action.Items.Add(new ActionPushItem { Type = ActionPushItemType.String, String = xItem.RequiredStringAttribute("value") }); break; case "StackFloat": action.Items.Add(new ActionPushItem { Type = ActionPushItemType.Float, Float = xItem.RequiredFloatAttribute("value") }); break; case "StackNull": action.Items.Add(new ActionPushItem { Type = ActionPushItemType.Null }); break; case "StackUndefined": action.Items.Add(new ActionPushItem { Type = ActionPushItemType.Undefined }); break; case "StackRegister": action.Items.Add(new ActionPushItem { Type = ActionPushItemType.Register, Register = xItem.RequiredByteAttribute("reg") }); break; case "StackBoolean": action.Items.Add(new ActionPushItem { Type = ActionPushItemType.Boolean, Boolean = xItem.RequiredByteAttribute("value") }); break; case "StackDouble": action.Items.Add(new ActionPushItem { Type = ActionPushItemType.Double, Double = xItem.RequiredDoubleAttribute("value") }); break; case "StackInteger": action.Items.Add(new ActionPushItem { Type = ActionPushItemType.Integer, Integer = xItem.RequiredIntAttribute("value") }); break; case "StackDictionaryLookup": action.Items.Add(new ActionPushItem { Type = ActionPushItemType.Constant8, Constant8 = xItem.RequiredByteAttribute("index") }); break; case "StackConstant16": action.Items.Add(new ActionPushItem { Type = ActionPushItemType.Constant16, Constant16 = xItem.RequiredUShortAttribute("value") }); break; default: throw new NotSupportedException(); } } return(action); }