/// <summary> /// Create an instance by specified byte array and start position. /// </summary> /// <returns>An System.Array that contains all array members.</returns> public override object Parse(ElementInstance parent, Stream stream, long stopAt) { Debug.Assert(DataElement != null); int len = EvalLength(parent, stream, stopAt); ArrayList list = new ArrayList(); for (int i = 0; i < len; i++) { list.Add(DataElement.Parse(parent, stream, stopAt)); } ArrayInstance inst = new ArrayInstance(parent, DataElement, list.ToArray()); return inst; }
public StructInstance(ElementInstance parent, Element[] elements) : base(parent) { _elements = elements; }
public ElementInstance(ElementInstance parent) { _parent = parent; }
public ArrayInstance(ElementInstance parent, Element type, Object[] elements) : base(parent) { this.Type = type; this.Elements = elements; }
private int EvalLength(ElementInstance parent, Stream stream, long stopAt) { int len = 0; if (Length == null) { Debug.Assert(stopAt >= stream.Position); len = (int)((stopAt - stream.Position) / DataElement.Size); } else { try { len = Convert.ToInt32(Length); } catch (FormatException) { IConvertible evalLen = parent.Eval(Length) as IConvertible; if (evalLen != null) { len = evalLen.ToInt32(null); } } } return len; }
/// <summary> /// Create an instance by specified byte array and start position. /// </summary> public override object Parse(ElementInstance parent, Stream stream, long stopAt) { StructInstance inst = new StructInstance(parent, Elements); if (Elements != null) { foreach (Element elem in Elements) { if (elem.EvalCondition(inst)) { if (stream.Position >= stopAt) { break; // don't read beyond boundary. } object elemInst = elem.Parse(inst, stream, stopAt); // Elements that don't have a name will not be added directly if (elem.Name != null && elem.Name != string.Empty) { inst[elem.Name] = elemInst; } } } } return inst; }
private void AddBitFields(ElementInstance parent, int data) { if (BitsFields != null && parent is StructInstance) { foreach (BitsField f in BitsFields) { Debug.Assert(f.length >= 1); int mask = (1 << f.length) - 1; int bits = (data >> f.offset) & mask; ((StructInstance) parent)[f.name] = bits; } } }
public override object Parse(ElementInstance parent, Stream stream, long stopAt) { char type = DataType[0]; char prefix = Char.ToLower(type); int size = Size; string dataType = DataType.ToLower(); if (prefix == 'b') // byte { if (size <= 1) { int b = stream.ReadByte(); AddBitFields(parent, b); return b; } else { byte[] data = new byte[size]; stream.Read( data, 0, size); return data; } } else if (prefix == 's') // fixed-length string { byte[] data = new byte[size]; stream.Read( data, 0, size); string s = Encoding.UTF8.GetString(data, 0, size); // a workaround for '\0'-stuffed stream if (s.IndexOf('\0') >= 0) { s = s.Substring( 0, s.IndexOf("\0")); } return s; } else if (prefix == 'z') // zero-ended string { size = (int) (stopAt - stream.Position); byte[] data = new byte[size]; stream.Read( data, 0, size); int z = Array.IndexOf(data, 0, 0, size); if (z < 0) z = data.Length; string s = Encoding.UTF8.GetString(data, 0, z); return s; } // vluimsbf8: Variable length code unsigned integer, most significant bit first. // The size of vluimsbf8 is a multiple of one byte. The first bit (Ext) of each // byte specifies if set to 1 that another byte is present for this vluimsbf8 code // word. The unsigned integer is encoded by the concatenation of the seven least // significant bits of each byte belonging to this vluimsbf8 code word. else if (prefix == 'v') { int i = 0; int b = 0x80; int bytes = 0; for (; (b & 0x80) != 0; bytes++) { b = stream.ReadByte(); i = i << 7 | (b & 0x7f); } if (type == 'v' && bytes > 1) { return Util.EndianFlip(i, bytes); } return i; } else if ("iuf".IndexOf(prefix) >= 0) // signed/unsigned integer { byte[] data = new byte[size]; stream.Read( data, 0, size); if (size == 8) { long i = data[0] | data[1] << 8 | data[2] << 16 | data[3] << 24 | data[4] << 32 | data[5] << 40 | data[6] << 48 | data[7] << 56; return i; } else if (size == 4 || size == 3) { int i; if (size == 4) { i = data[0] | data[1] << 8 | data[2] << 16 | data[3] << 24; } else { i = data[0] | data[1] << 8 | data[2] << 16; } // Big-indian integer is identified by upper case 'I' if (type == 'I') { return Util.EndianFlip(i, size); } // Big-indian unsigned integer is identified by upper case 'U' else if (type == 'U') { return Util.EndianFlip((uint) i, size); } else if (type == 'u') { return (uint) i; } return i; } else if (size == 2) { short i = (short) (data[0] | data[1] << 8); if (type == 'I') { return (short) Util.EndianFlip((int) i, size); } else if (type == 'U') { return (ushort) Util.EndianFlip(((uint) i), size); } else if (type == 'u') { return (ushort) i; } return i; } else { Debug.Assert( false, "Invalid field size!"); } } return null; }
/// <summary> /// To construct instance from specified stream. /// </summary> /// <param name="parent"></param> /// <param name="stream"></param> /// <param name="stopAt"></param> /// <returns></returns> public abstract object Parse(ElementInstance parent, Stream stream, long stopAt);
/// <summary> /// Evaluate bool expression /// </summary> /// <param name="inst"></param> /// <returns></returns> public bool EvalCondition(ElementInstance inst) { if (Condition != null) { try { BoolExprLexer lexer = new BoolExprLexer(new StringReader(Condition)); BoolExprParser parser = new BoolExprParser(lexer); ConditionEvaluator treeParser = new ConditionEvaluator(); parser.expression(); antlr.collections.AST ast = parser.getAST(); treeParser.Instance = inst; return treeParser.expression(ast); } catch (Exception ex) { Debug.Write(ex); return false; } } return true; }