Example #1
0
 public override CodeNode VisitWriteType(WriteTypeNode node)
 {
     _Writer.WriteStartElement("WriteType");
     _Writer.WriteAttributeString("Type", node.Type.ToString());
     _Writer.WriteStartElement("ValueSource");
     Visit(node.ValueSource);
     _Writer.WriteEndElement();
     _Writer.WriteEndElement();
     return(node);
 }
Example #2
0
        public virtual CodeNode VisitWriteType(WriteTypeNode node)
        {
            var visited = Visit(node.ValueSource);

            if (visited == node.ValueSource)
            {
                return(node);
            }
            else
            {
                return(new WriteTypeNode(node.Type, visited));
            }
        }
        CodeNode GenerateAssignment(KeyValuePair <FieldLayoutAttribute, PropertyInfo> pair)
        {
            var fieldType = pair.Key.FieldType;
            StringFieldLayoutAttribute stringLayout = pair.Key as StringFieldLayoutAttribute;
            ArrayFieldLayoutAttribute  arrayLayout  = pair.Key as ArrayFieldLayoutAttribute;

            //if it is an array, defer to GenerateArrayAssignment
            if (arrayLayout != null)
            {
                // 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));
            }

            var initNodes = new List <CodeNode>();

            bool localWasPresent = true;

            if (_FieldLocalsTouched.Add(pair.Key.FieldIndex))
            {
                localWasPresent = false;
                //add a create local node
                initNodes.Add(new CreateFieldLocalForWritingNode(pair.Key.FieldIndex, pair.Key.FieldType));
                _FieldLocalsTouched.Add(pair.Key.FieldIndex);
            }

            //find out if there is an optional field flag that we need to manage
            FieldLayoutAttribute        optionalFieldLayout          = null;
            FlaggedFieldLayoutAttribute currentAsOptionalFieldLayout = pair.Key as FlaggedFieldLayoutAttribute;

            if (currentAsOptionalFieldLayout != null)
            {
                optionalFieldLayout = _Fields[currentAsOptionalFieldLayout.FlagIndex].Key;
                if (_FieldLocalsTouched.Add(currentAsOptionalFieldLayout.FlagIndex))
                {
                    initNodes.Add(new CreateFieldLocalForWritingNode(currentAsOptionalFieldLayout.FlagIndex, optionalFieldLayout.FieldType));
                }
            }

            //this will hold a node that will write in the case we have no value to write
            CodeNode noValueWriteContingency = null;
            //this will hold the source of the write that will happen above
            CodeNode noValueWriteContingencySource = null;

            //Decide what to do if we don't have a value to write.
            //This will happen if we don't store the value in a property, it is "missing" from the property source, or something else
            //TODO: should these have a different precedence?
            if (pair.Key.MissingValue != null)
            {
                //if we have a missing value, set that as the write source
                noValueWriteContingencySource = new LoadMissingValueNode(pair.Key.MissingValue, fieldType);
            }
            else if (localWasPresent || optionalFieldLayout != null)
            {
                //if the local was present when we started, that means it was initialized by another field. We can safely write it
                //Similarly, if this is marked as an optional field, we can still write whatever the value of the local is (cheat)
                noValueWriteContingencySource = new LoadFieldLocalNode(pair.Key.FieldIndex);
            }
            else if (fieldType.IsValueType)
            {
                //if T is a value type, we're up a creek with nothing to write.
                //this is obviously not a good place, so throw in the converter
                noValueWriteContingency = new ThrowInvalidOperationNode(string.Format(Resources.NonNullableField, pair.Key.FieldIndex, _Type));
            }
            else
            {
                //otherwise, we can try to write null (unless it is a fixed-length string, which should have a default instead)
                if (stringLayout != null && stringLayout.Length > 0)
                {
                    //TODO: move this check into StdfStringLayout if we can, along with a check that the missing value length matches
                    throw new NotSupportedException(Resources.FixedLengthStringMustHaveDefault);
                }
                noValueWriteContingencySource = new LoadNullNode();
            }

            //create the write node and the no-value contingency if we don't already have one
            CodeNode writeNode;

            if (stringLayout != null && stringLayout.Length > 0)
            {
                noValueWriteContingency = noValueWriteContingency ?? new WriteFixedStringNode(stringLayout.Length, noValueWriteContingencySource);
                writeNode = new WriteFixedStringNode(stringLayout.Length, new LoadFieldLocalNode(pair.Key.FieldIndex));
            }
            else
            {
                noValueWriteContingency = noValueWriteContingency ?? new WriteTypeNode(fieldType, noValueWriteContingencySource);
                writeNode = new WriteTypeNode(fieldType, new LoadFieldLocalNode(pair.Key.FieldIndex));
            }
            //return the crazy node
            //TODO: refactor this better, this sucks
            return(new WriteFieldNode(pair.Key.FieldIndex, fieldType,
                                      initialization: new BlockNode(initNodes),
                                      sourceProperty: pair.Value,
                                      writeOperation: writeNode,
                                      noValueWriteContingency: noValueWriteContingency,
                                      optionalFieldIndex: optionalFieldLayout == null ? null : (int?)optionalFieldLayout.FieldIndex,
                                      optionalFieldMask: optionalFieldLayout == null ? (byte)0 : currentAsOptionalFieldLayout.FlagMask));
        }
Example #4
0
        public override CodeNode VisitWriteType(WriteTypeNode node)
        {
            MethodInfo writeMethod;

            if (node.IsNibble)
            {
                writeMethod = typeof(BinaryWriter).GetMethod(nameof(BinaryWriter.WriteNibbleArray), node.Type);
            }
            else if (!_WriteMethods.TryGetValue(node.Type, out writeMethod))
            {
                string writeMethodName;
                if (node.Type == typeof(byte))
                {
                    writeMethodName = "WriteByte";
                }
                else if (node.Type == typeof(byte[]))
                {
                    writeMethodName = "WriteByteArray";
                }
                else if (node.Type == typeof(sbyte))
                {
                    writeMethodName = "WriteSByte";
                }
                else if (node.Type == typeof(sbyte[]))
                {
                    writeMethodName = "WriteSByteArray";
                }
                else if (node.Type == typeof(ushort))
                {
                    writeMethodName = "WriteUInt16";
                }
                else if (node.Type == typeof(ushort[]))
                {
                    writeMethodName = "WriteUInt16Array";
                }
                else if (node.Type == typeof(short))
                {
                    writeMethodName = "WriteInt16";
                }
                else if (node.Type == typeof(short[]))
                {
                    writeMethodName = "WriteInt16Array";
                }
                else if (node.Type == typeof(uint))
                {
                    writeMethodName = "WriteUInt32";
                }
                else if (node.Type == typeof(uint[]))
                {
                    writeMethodName = "WriteUInt32Array";
                }
                else if (node.Type == typeof(int))
                {
                    writeMethodName = "WriteInt32";
                }
                else if (node.Type == typeof(int[]))
                {
                    writeMethodName = "WriteInt32Array";
                }
                else if (node.Type == typeof(ulong))
                {
                    writeMethodName = "WriteUInt64";
                }
                else if (node.Type == typeof(ulong[]))
                {
                    writeMethodName = "WriteUInt64Array";
                }
                else if (node.Type == typeof(long))
                {
                    writeMethodName = "WriteInt64";
                }
                else if (node.Type == typeof(long[]))
                {
                    writeMethodName = "WriteInt64Array";
                }
                else if (node.Type == typeof(float))
                {
                    writeMethodName = "WriteSingle";
                }
                else if (node.Type == typeof(float[]))
                {
                    writeMethodName = "WriteSingleArray";
                }
                else if (node.Type == typeof(double))
                {
                    writeMethodName = "WriteDouble";
                }
                else if (node.Type == typeof(double[]))
                {
                    writeMethodName = "WriteDoubleArray";
                }
                else if (node.Type == typeof(string))
                {
                    writeMethodName = "WriteString";
                }
                else if (node.Type == typeof(string[]))
                {
                    writeMethodName = "WriteStringArray";
                }
                else if (node.Type == typeof(DateTime))
                {
                    writeMethodName = "WriteDateTime";
                }
                else if (node.Type == typeof(BitArray))
                {
                    writeMethodName = "WriteBitArray";
                }
                else
                {
                    throw new NotSupportedException(string.Format(Resources.UnsupportedWriterType, node.Type));
                }
                writeMethod = typeof(BinaryWriter).GetMethod(writeMethodName, node.Type);
                _WriteMethods[node.Type] = writeMethod;
            }

            ILGen.Ldloc(_Writer);
            Visit(node.ValueSource);
            Log($"Writing with {writeMethod.Name}.");
            ILGen.Callvirt(writeMethod);
            return(node);
        }