using System.Runtime.InteropServices;
using Mono.CompilerServices.SymbolWriter;
using System.Linq;
+using System.IO;
+using System.Security.Cryptography;
+using Mono.Security.Cryptography;
#if STATIC
using IKVM.Reflection;
sealed class StaticDataContainer : CompilerGeneratedContainer
{
readonly Dictionary<int, Struct> size_types;
- int fields;
+ readonly Dictionary<string, FieldSpec> data_hashes;
public StaticDataContainer (ModuleContainer module)
- : base (module, new MemberName ("<PrivateImplementationDetails>" + module.builder.ModuleVersionId.ToString ("B"), Location.Null),
+ : base (module, new MemberName ("<PrivateImplementationDetails>", Location.Null),
Modifiers.STATIC | Modifiers.INTERNAL)
{
size_types = new Dictionary<int, Struct> ();
+ data_hashes = new Dictionary<string, FieldSpec> (StringComparer.Ordinal);
}
public override void CloseContainer ()
size_type.TypeBuilder.__SetLayout (1, data.Length);
}
- var name = "$field-" + fields.ToString ("X");
- ++fields;
- const Modifiers fmod = Modifiers.STATIC | Modifiers.INTERNAL;
- var fbuilder = TypeBuilder.DefineField (name, size_type.CurrentType.GetMetaInfo (), ModifiersExtensions.FieldAttr (fmod) | FieldAttributes.HasFieldRVA);
- fbuilder.__SetDataAndRVA (data);
+ FieldSpec fs;
+ var data_hash = GenerateDataFieldName (data);
+ if (!data_hashes.TryGetValue (data_hash, out fs)) {
+ var name = "$field-" + data_hash;
+ const Modifiers fmod = Modifiers.STATIC | Modifiers.INTERNAL | Modifiers.READONLY;
+ var fbuilder = TypeBuilder.DefineField (name, size_type.CurrentType.GetMetaInfo (), ModifiersExtensions.FieldAttr (fmod) | FieldAttributes.HasFieldRVA);
+ fbuilder.__SetDataAndRVA (data);
- return new FieldSpec (CurrentType, null, size_type.CurrentType, fbuilder, fmod);
+ fs = new FieldSpec (CurrentType, null, size_type.CurrentType, fbuilder, fmod);
+ data_hashes.Add (data_hash, fs);
+ }
+
+ return fs;
+ }
+
+ static string GenerateDataFieldName (byte[] bytes)
+ {
+ using (var hashProvider = new SHA1CryptoServiceProvider ())
+ {
+ return CryptoConvert.ToHex (hashProvider.ComputeHash (bytes));
+ }
}
}
readonly Dictionary<TypeSpec, ReferenceContainer> reference_types;
readonly Dictionary<TypeSpec, MethodSpec> attrs_cache;
readonly Dictionary<TypeSpec, AwaiterDefinition> awaiters;
+ readonly Dictionary<TypeSpec, TypeInfo> type_info_cache;
AssemblyDefinition assembly;
readonly CompilerContext context;
reference_types = new Dictionary<TypeSpec, ReferenceContainer> ();
attrs_cache = new Dictionary<TypeSpec, MethodSpec> ();
awaiters = new Dictionary<TypeSpec, AwaiterDefinition> ();
+ type_info_cache = new Dictionary<TypeSpec, TypeInfo> ();
}
#region Properties
}
}
+ internal Dictionary<TypeSpec, TypeInfo> TypeInfoCache {
+ get {
+ return type_info_cache;
+ }
+ }
+
public override string[] ValidAttributeTargets {
get {
return attribute_targets;
}
}
+ public Dictionary<string, string> GetResourceStrings { get; private set; }
+
#endregion
public override void Accept (StructuralVisitor visitor)
// TODO: This setter is quite ugly but I have not found a way around it yet
this.assembly = assembly;
}
+
+ public void LoadGetResourceStrings (List<string> fileNames)
+ {
+ foreach (var fileName in fileNames) {
+ if (!File.Exists (fileName)) {
+ Report.Error (1566, "Error reading resource file `{0}'", fileName);
+ return;
+ }
+
+ foreach (var l in File.ReadLines (fileName)) {
+ if (GetResourceStrings == null)
+ GetResourceStrings = new Dictionary<string, string> ();
+
+ var line = l.Trim ();
+ if (line.Length == 0 || line [0] == '#' || line [0] == ';')
+ continue;
+
+ var epos = line.IndexOf ('=');
+ if (epos < 0)
+ continue;
+
+ var key = line.Substring (0, epos).Trim ();
+ var value = line.Substring (epos + 1).Trim ();
+
+ GetResourceStrings [key] = value;
+ }
+ }
+ }
}
}