Last active
September 12, 2016 14:00
-
-
Save migueldeicaza/96c2bc52bfc30aa47a3ba34ce135e6f1 to your computer and use it in GitHub Desktop.
Implicit string constant to byte[]/byte* conversions for C#
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/mcs/mcs/constant.cs b/mcs/mcs/constant.cs | |
old mode 100644 | |
new mode 100755 | |
index a0ae78c..0f45e74 | |
--- a/mcs/mcs/constant.cs | |
+++ b/mcs/mcs/constant.cs | |
@@ -12,6 +12,7 @@ | |
using System; | |
using System.Globalization; | |
+using System.Text; | |
#if STATIC | |
using IKVM.Reflection.Emit; | |
@@ -2135,10 +2136,134 @@ namespace Mono.CSharp { | |
if (IsDefaultValue && type.BuiltinType == BuiltinTypeSpec.Type.Object) | |
return new NullConstant (type, loc); | |
+ // | |
+ // From string to byte [] | |
+ // | |
+ if (type.Kind == MemberKind.ArrayType){ | |
+ var atype = (ArrayContainer)type; | |
+ if (atype.Rank == 1 && atype.Element.BuiltinType == BuiltinTypeSpec.Type.Byte) { | |
+ return new ByteArrayConstant (type, Value, Encoding.UTF8.GetBytes (Value), Location); | |
+ } | |
+ } | |
+ // | |
+ // From string to byte * | |
+ // | |
+ if (type.Kind == MemberKind.PointerType) { | |
+ var ptype = type as PointerContainer; | |
+ if (ptype.Element.BuiltinType == BuiltinTypeSpec.Type.Byte) { | |
+ return new BytePtrArrayConstant (type, Value, Encoding.UTF8.GetBytes (Value), Location); | |
+ } | |
+ } | |
return base.ConvertImplicitly (type); | |
} | |
} | |
+ abstract class ByteArrayConstantBase : Constant | |
+ { | |
+ public ByteArrayConstantBase (TypeSpec type, string strValue, byte [] values, Location loc) | |
+ : base (loc) | |
+ { | |
+ this.type = type; | |
+ eclass = ExprClass.Value; | |
+ | |
+ Value = values; | |
+ StrValue = strValue; | |
+ } | |
+ | |
+ public byte [] Value { get; protected set; } | |
+ string StrValue; | |
+ | |
+ public override object GetValue () | |
+ { | |
+ return Value; | |
+ } | |
+ | |
+ public override string GetValueAsLiteral () | |
+ { | |
+ | |
+ return "\"" + StrValue + "\""; | |
+ } | |
+ | |
+ public override long GetValueAsLong () | |
+ { | |
+ throw new NotSupportedException (); | |
+ } | |
+ | |
+ public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType) | |
+ { | |
+ // cast to object | |
+ if (type != targetType) | |
+ enc.Encode (type); | |
+ | |
+ enc.Encode (StrValue); | |
+ } | |
+ | |
+ public override bool IsDefaultValue { | |
+ get { | |
+ return Value == null; | |
+ } | |
+ } | |
+ | |
+ public override bool IsNegative { | |
+ get { | |
+ return false; | |
+ } | |
+ } | |
+ | |
+ public override bool IsNull { | |
+ get { | |
+ return IsDefaultValue; | |
+ } | |
+ } | |
+ | |
+ public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type) | |
+ { | |
+ return null; | |
+ } | |
+ | |
+ public override Constant ConvertImplicitly (TypeSpec type) | |
+ { | |
+ return null; | |
+ } | |
+ } | |
+ | |
+ class BytePtrArrayConstant : ByteArrayConstantBase { | |
+ public BytePtrArrayConstant (TypeSpec type, string strValue, byte [] values, Location loc) | |
+ : base (type, strValue, values, loc) | |
+ { | |
+ } | |
+ | |
+ public override void Emit (EmitContext ec) | |
+ { | |
+ var fb = ec.CurrentTypeDefinition.Module.MakeStaticData (Value, loc); | |
+ ec.Emit (OpCodes.Ldsflda, fb); | |
+ } | |
+ } | |
+ | |
+ class ByteArrayConstant : ByteArrayConstantBase | |
+ { | |
+ public ByteArrayConstant (TypeSpec type, string strValue, byte [] values, Location loc) | |
+ : base (type, strValue, values, loc) | |
+ { | |
+ } | |
+ | |
+ public override void Emit (EmitContext ec) | |
+ { | |
+ var m = ec.Module.PredefinedMembers.RuntimeHelpersInitializeArray.Resolve (loc); | |
+ if (m == null) | |
+ return; | |
+ | |
+ ec.EmitInt (Value.Length); | |
+ ec.ig.Emit (OpCodes.Newarr, (type as ArrayContainer).Element.GetMetaInfo ()); | |
+ ec.Emit (OpCodes.Dup); | |
+ | |
+ var fb = ec.CurrentTypeDefinition.Module.MakeStaticData (Value, loc); | |
+ ec.Emit (OpCodes.Ldtoken, fb); | |
+ ec.Emit (OpCodes.Call, m); | |
+ } | |
+ | |
+ | |
+ } | |
class NameOf : StringConstant | |
{ | |
readonly SimpleName name; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment