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); }
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)); }
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); }