Skip to content

Instantly share code, notes, and snippets.

@migueldeicaza
Last active September 12, 2016 14:00
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save migueldeicaza/96c2bc52bfc30aa47a3ba34ce135e6f1 to your computer and use it in GitHub Desktop.
Save migueldeicaza/96c2bc52bfc30aa47a3ba34ce135e6f1 to your computer and use it in GitHub Desktop.
Implicit string constant to byte[]/byte* conversions for C#
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