Exemple #1
0
        CodeNode GenerateArrayAssignment(KeyValuePair <FieldLayoutAttribute, PropertyInfo> pair)
        {
            var  fieldType     = pair.Key.FieldType;
            bool isNibbleArray = pair.Key is NibbleArrayFieldLayoutAttribute;
            int  lengthIndex   = ((ArrayFieldLayoutAttribute)pair.Key).ArrayLengthFieldIndex;

            //we can skip entirely if the length field was zero
            //we'll combine this as part of the "reading" of the field
            var parseConditionNode = new SkipArrayAssignmentIfLengthIsZeroNode(lengthIndex);

            //find out if we should even parse this field
            if (pair.Value != null && !ShouldParseField(pair.Value.Name))
            {
                //we can simply return this skip node since it effectively encapsulates the length check as well
                return(new SkipTypeNode(fieldType.MakeArrayType(), lengthIndex));
            }
            else
            {
                var       readNode        = new ReadTypeNode(fieldType.MakeArrayType(), lengthIndex, isNibble: isNibbleArray);
                BlockNode assignmentBlock = null;
                if (pair.Value != null)
                {
                    assignmentBlock = new BlockNode(new AssignFieldToPropertyNode(fieldType.MakeArrayType(), pair.Value));
                }
                //return a FieldAssignmentNode.  Note we're combining the parseConditionNode and the readNode.
                return(new FieldAssignmentNode(fieldType.MakeArrayType(), pair.Key.FieldIndex, new BlockNode(parseConditionNode, readNode), assignmentBlock));
            }
        }
 public override CodeNode VisitReadType(ReadTypeNode node)
 {
     _Writer.WriteStartElement("ReadType");
     _Writer.WriteAttributeString("IsNibble", node.IsNibble.ToString());
     _Writer.WriteAttributeString("LengthIndex", node.LengthIndex.ToString());
     _Writer.WriteAttributeString("Type", node.Type.ToString());
     _Writer.WriteEndElement();
     return(node);
 }
        public override CodeNode VisitReadType(ReadTypeNode node)
        {
            if (_FieldLocal == null)
            {
                throw new InvalidOperationException("Cannot read string outside a FieldAssignmentNode");
            }
            MethodInfo readTypeMethod;
            var        argsArray = node.Type.IsArray ? new[] { typeof(int) } : new Type[0];

            if (node.IsNibble)
            {
                readTypeMethod = typeof(BinaryReader).GetMethod("ReadNibbleArray", argsArray);
            }
            else if (!_ReadTypeMethods.TryGetValue(node.Type, out readTypeMethod))
            {
                string readTypeMethodName;
                if (node.Type == typeof(byte))
                {
                    readTypeMethodName = "ReadByte";
                }
                else if (node.Type == typeof(byte[]))
                {
                    readTypeMethodName = "ReadByteArray";
                }
                else if (node.Type == typeof(sbyte))
                {
                    readTypeMethodName = "ReadSByte";
                }
                else if (node.Type == typeof(sbyte[]))
                {
                    readTypeMethodName = "ReadSByteArray";
                }
                else if (node.Type == typeof(ushort))
                {
                    readTypeMethodName = "ReadUInt16";
                }
                else if (node.Type == typeof(ushort[]))
                {
                    readTypeMethodName = "ReadUInt16Array";
                }
                else if (node.Type == typeof(short))
                {
                    readTypeMethodName = "ReadInt16";
                }
                else if (node.Type == typeof(short[]))
                {
                    readTypeMethodName = "ReadInt16Array";
                }
                else if (node.Type == typeof(uint))
                {
                    readTypeMethodName = "ReadUInt32";
                }
                else if (node.Type == typeof(uint[]))
                {
                    readTypeMethodName = "ReadUInt32Array";
                }
                else if (node.Type == typeof(int))
                {
                    readTypeMethodName = "ReadInt32";
                }
                else if (node.Type == typeof(int[]))
                {
                    readTypeMethodName = "ReadInt32Array";
                }
                else if (node.Type == typeof(ulong))
                {
                    readTypeMethodName = "ReadUInt64";
                }
                else if (node.Type == typeof(ulong[]))
                {
                    readTypeMethodName = "ReadUInt64Array";
                }
                else if (node.Type == typeof(long))
                {
                    readTypeMethodName = "ReadInt64";
                }
                else if (node.Type == typeof(long[]))
                {
                    readTypeMethodName = "ReadInt64Array";
                }
                else if (node.Type == typeof(float))
                {
                    readTypeMethodName = "ReadSingle";
                }
                else if (node.Type == typeof(float[]))
                {
                    readTypeMethodName = "ReadSingleArray";
                }
                else if (node.Type == typeof(double))
                {
                    readTypeMethodName = "ReadDouble";
                }
                else if (node.Type == typeof(double[]))
                {
                    readTypeMethodName = "ReadDoubleArray";
                }
                else if (node.Type == typeof(string))
                {
                    readTypeMethodName = "ReadString";
                }
                else if (node.Type == typeof(string[]))
                {
                    readTypeMethodName = "ReadStringArray";
                }
                else if (node.Type == typeof(DateTime))
                {
                    readTypeMethodName = "ReadDateTime";
                }
                else if (node.Type == typeof(BitArray))
                {
                    readTypeMethodName = "ReadBitArray";
                }
                else
                {
                    throw new NotSupportedException(string.Format(Resources.UnsupportedReaderType, node.Type));
                }
                readTypeMethod = typeof(BinaryReader).GetMethod(readTypeMethodName, argsArray);
                _ReadTypeMethods[node.Type] = readTypeMethod;
            }
            Log($"Reading with {readTypeMethod.Name}.");

            ILGen.Ldloc(_Reader);
            //if we have a length index, load its local (we enforce its presence for arrays in the node)
            if (node.LengthIndex.HasValue)
            {
                ILGen.Ldloc(_FieldLocals[node.LengthIndex.Value]);
            }
            ILGen.Callvirt(readTypeMethod);
            ILGen.Stloc(_FieldLocal);
            return(node);
        }
Exemple #4
0
        CodeNode GenerateAssignment(KeyValuePair <FieldLayoutAttribute, PropertyInfo> pair)
        {
            var fieldType = pair.Key.FieldType;

            //if this is an array, defer to GenerateArrayAssignment
            if (pair.Key is ArrayFieldLayoutAttribute)
            {
                // TODO: Why do we need these fieldType checks at all?
                if (fieldType == typeof(string))
                {
                    // TODO: Accept string arrays
                    throw new InvalidOperationException(Resources.NoStringArrays);
                }
                if (fieldType == typeof(BitArray))
                {
                    throw new InvalidOperationException(Resources.NoBitArrayArrays);
                }
                return(GenerateArrayAssignment(pair));
            }

            //get the length if this is a fixed-length string
            var stringLength = -1;

            if (pair.Key is StringFieldLayoutAttribute stringLayout && stringLayout.Length > 0)
            {
                stringLength = stringLayout.Length;
            }

            //just skip this field if we have an assignment, but shouldn't be parsing it
            if (pair.Value != null && !ShouldParseField(pair.Value.Name))
            {
                if (stringLength > 0)
                {
                    return(new SkipRawBytesNode(stringLength));
                }
                else
                {
                    return(new SkipTypeNode(fieldType));
                }
            }

            //determine how we'll read the field
            CodeNode readerNode;

            if (stringLength > 0)
            {
                readerNode = new ReadFixedStringNode(stringLength);
            }
            else
            {
                readerNode = new ReadTypeNode(fieldType);
            }

            BlockNode assignmentBlock = null;

            //if we have a property to assign to, generate the appropriate assignment statements
            if (pair.Value != null)
            {
                var assignmentNodes = new List <CodeNode>();
                //if this is optional, set us up to skip if the missing flag is set
                if (pair.Key is FlaggedFieldLayoutAttribute optionalLayout)
                {
                    assignmentNodes.Add(new SkipAssignmentIfFlagSetNode(optionalLayout.FlagIndex, optionalLayout.FlagMask));
                }
                //if we have a missing value, set us up to skip if the value matches the missing value
                else if (pair.Key.MissingValue != null && !pair.Key.PersistMissingValue)
                {
                    if (!(fieldType.IsAssignableFrom(pair.Key.MissingValue.GetType())))
                    {
                        throw new InvalidOperationException(string.Format("Missing value {0} is not assignable to {1}.", pair.Key.MissingValue, fieldType));
                    }
                    assignmentNodes.Add(new SkipAssignmentIfMissingValueNode(pair.Key.MissingValue));
                }
                //set us up to assign to the property
                assignmentNodes.Add(new AssignFieldToPropertyNode(fieldType, pair.Value));
                assignmentBlock = new BlockNode(assignmentNodes);
            }
            return(new FieldAssignmentNode(fieldType, pair.Key.FieldIndex, readerNode, assignmentBlock));
        }
Exemple #5
0
 public virtual CodeNode VisitReadType(ReadTypeNode node)
 {
     return(node);
 }