Skip to content

Commit

Permalink
introduce the RtxtParser and RtxtWriter
Browse files Browse the repository at this point in the history
  • Loading branch information
dellis1972 committed Jan 24, 2022
1 parent 2614a88 commit 806f6ea
Show file tree
Hide file tree
Showing 7 changed files with 179 additions and 98 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,21 @@ protected void ClearDesignerClass (TypeDefinition designer)
designer.Events.Clear ();
}

protected Dictionary<string, int> BuildResourceDesignerFieldLookup (TypeDefinition type)
{
var output = new Dictionary<string, int> ();
foreach (TypeDefinition definition in type.NestedTypes)
{
foreach (FieldDefinition field in definition.Fields)
{
string key = $"{definition.Name}::{field.Name}";
if (!output.ContainsKey (key))
output.Add(key, int.Parse (field.Constant?.ToString () ?? "0"));
}
}
return output;
}

protected void FixType (TypeDefinition type, TypeDefinition localDesigner)
{
foreach (MethodDefinition method in type.Methods)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,21 +60,6 @@ protected override void EndProcess ()
}
}

Dictionary<string, int> BuildResourceDesignerFieldLookup (TypeDefinition type)
{
var output = new Dictionary<string, int> ();
foreach (TypeDefinition definition in type.NestedTypes)
{
foreach (FieldDefinition field in definition.Fields)
{
string key = $"{definition.Name}::{field.Name}";
if (!output.ContainsKey (key))
output.Add(key, int.Parse (field.Constant?.ToString () ?? "0"));
}
}
return output;
}

protected override void FixBody (MethodBody body, TypeDefinition designer)
{
Dictionary<Instruction, int> instructions = new Dictionary<Instruction, int>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,21 @@ bool Run(DirectoryAssemblyResolver res) {
CreateCtor (resourceDesigner, module);
module.Types.Add(resourceDesigner);

if (File.Exists (RTxtFile.ItemSpec))
ProcessRtxtFile (RTxtFile.ItemSpec, resourceDesigner, module);
if (File.Exists (RTxtFile.ItemSpec)) {
var parser = new RtxtParser ();
var resources = parser.Parse (RTxtFile.ItemSpec, Log, resource_fixup);
foreach (var resource in resources) {
var r = resource.Value;
switch (r.Type) {
case RType.Integer:
CreateIntProperty (resource.Key, r.Identifier, r.Id, resourceDesigner, module);
break;
case RType.Array:
CreateIntArrayProperty (resource.Key, r.Identifier, r.Ids, resourceDesigner, module);
break;
}
}
}

assembly.Write (OutputFile.ItemSpec);
return !Log.HasLoggedErrors;
Expand All @@ -138,59 +151,6 @@ MethodReference ImportCustomAttributeConstructor (string type, ModuleDefinition
return module.ImportReference (tv.Methods.First(x => x.IsConstructor));
}

void ProcessRtxtFile (string file, TypeDefinition resourceDesigner, ModuleDefinition module)
{
var lines = System.IO.File.ReadLines (file);
foreach (var line in lines) {
var items = line.Split (new char [] { ' ' }, 4);
int value = items [1] != "styleable" ? Convert.ToInt32 (items [3], 16) : -1;
string itemName = GetResourceName(items [1], items [2], resource_fixup);
switch (items [1]) {
case "anim":
case "animator":
case "attr":
case "array":
case "bool":
case "color":
case "dimen":
case "drawable":
case "font":
case "id":
case "integer":
case "interpolator":
case "layout":
case "menu":
case "mipmap":
case "plurals":
case "raw":
case "string":
case "style":
case "transition":
case "xml":
CreateIntProperty (items [1], itemName, value, resourceDesigner, module);
break;
case "styleable":
switch (items [0]) {
case "int":
CreateIntProperty (items[1], itemName, Convert.ToInt32 (items [3], 10), resourceDesigner, module);
break;
case "int[]":
var arrayValues = items [3].Trim (new char [] { '{', '}' })
.Replace (" ", "")
.Split (new char [] { ',' });
CreateIntArrayProperty (items[1], itemName,
arrayValues.Select (x => string.IsNullOrEmpty (x) ? -1 : Convert.ToInt32 (x, 16)).ToArray (), resourceDesigner, module);
break;
}
break;
// for custom views
default:
CreateIntProperty (items [1], itemName, value, resourceDesigner, module);
break;
}
}
}

void CreateIntProperty (string resourceClass, string propertyName, int value, TypeDefinition resourceDesigner, ModuleDefinition module)
{
TypeDefinition nestedType = CreateResourceClass (resourceDesigner, resourceClass, module);
Expand Down Expand Up @@ -265,21 +225,5 @@ PropertyDefinition CreateArrayProperty (string propertyName, IEnumerable<int> va
il.Emit (OpCodes.Ret);
return p;
}

// TODO: Borrowed code!
internal string GetResourceName (string type, string name, Dictionary<string, string> map)
{
string mappedValue;
string key = string.Format ("{0}{1}{2}", type, Path.DirectorySeparatorChar, name).ToLowerInvariant ();

if (map.TryGetValue (key, out mappedValue)) {
Log.LogDebugMessage (" - Remapping resource: {0}.{1} -> {2}", type, name, mappedValue);
return ResourceIdentifier.CreateValidIdentifier (mappedValue.Substring (mappedValue.LastIndexOf (Path.DirectorySeparatorChar) + 1));
}

Log.LogDebugMessage (" - Not remapping resource: {0}.{1}", type, name);

return ResourceIdentifier.CreateValidIdentifier (name);
}
}
}
18 changes: 17 additions & 1 deletion src/Xamarin.Android.Build.Tasks/Utilities/ResourceIdentifier.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
using Microsoft.Android.Build.Tasks;
using Microsoft.Build.Utilities;

namespace Xamarin.Android.Tasks
Expand Down Expand Up @@ -42,5 +43,20 @@ public static string CreateValidIdentifier (string identifier)

return result;
}

internal static string GetResourceName (string type, string name, Dictionary<string, string> map, TaskLoggingHelper log)
{
string mappedValue;
string key = string.Format ("{0}{1}{2}", type, Path.DirectorySeparatorChar, name).ToLowerInvariant ();

if (map.TryGetValue (key, out mappedValue)) {
log.LogDebugMessage (" - Remapping resource: {0}.{1} -> {2}", type, name, mappedValue);
return ResourceIdentifier.CreateValidIdentifier (mappedValue.Substring (mappedValue.LastIndexOf (Path.DirectorySeparatorChar) + 1));
}

log.LogDebugMessage (" - Not remapping resource: {0}.{1}", type, name);

return ResourceIdentifier.CreateValidIdentifier (name);
}
}
}
}
12 changes: 1 addition & 11 deletions src/Xamarin.Android.Build.Tasks/Utilities/ResourceParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,17 +40,7 @@ internal static string GetNestedTypeName (string name)

internal string GetResourceName (string type, string name, Dictionary<string, string> map)
{
string mappedValue;
string key = string.Format ("{0}{1}{2}", type, Path.DirectorySeparatorChar, name).ToLowerInvariant ();

if (map.TryGetValue (key, out mappedValue)) {
Log.LogDebugMessage (" - Remapping resource: {0}.{1} -> {2}", type, name, mappedValue);
return ResourceIdentifier.CreateValidIdentifier (mappedValue.Substring (mappedValue.LastIndexOf (Path.DirectorySeparatorChar) + 1));
}

Log.LogDebugMessage (" - Not remapping resource: {0}.{1}", type, name);

return ResourceIdentifier.CreateValidIdentifier (name);
return ResourceIdentifier.GetResourceName (type, name, map, Log);
}

}
Expand Down
113 changes: 113 additions & 0 deletions src/Xamarin.Android.Build.Tasks/Utilities/RtxtParser.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Microsoft.Android.Build.Tasks;
using Microsoft.Build.Utilities;

namespace Xamarin.Android.Tasks
{
public enum RType {
Integer,
Array,
}
public struct R {
public RType Type = RType.Integer;
public int Id;
public int [] Ids;
public string Identifier;
public string ResourceType;

public override string ToString () {
if (Type == RType.Integer)
return $"int {ResourceType} {Identifier} 0x{Id.ToString ("x")}";
return $"int[] {ResourceType} {Identifier} {{{String.Join (",", Ids.Select (x => $"0x{x.ToString ("x")}"))}}}";
}
}

public class RtxtParser {

TaskLoggingHelper log;
Dictionary<string, string> map;

Dictionary<string, string> resource_fixup = new Dictionary<string, string> (StringComparer.OrdinalIgnoreCase);
public Dictionary<string, R> Parse (string file, TaskLoggingHelper logger, Dictionary<string, string> mapping){
log = logger;
map = mapping;
var result = new Dictionary<string, R> ();
if (File.Exists (file))
ProcessRtxtFile (file, result);
return result;
}

void ProcessRtxtFile (string file, Dictionary<string, R> result)
{
var lines = File.ReadLines (file);
foreach (var line in lines) {
var items = line.Split (new char [] { ' ' }, 4);
int value = items [1] != "styleable" ? Convert.ToInt32 (items [3], 16) : -1;
string itemName = ResourceIdentifier.GetResourceName(items [1], items [2], resource_fixup, log);
switch (items [1]) {
case "anim":
case "animator":
case "attr":
case "array":
case "bool":
case "color":
case "dimen":
case "drawable":
case "font":
case "id":
case "integer":
case "interpolator":
case "layout":
case "menu":
case "mipmap":
case "plurals":
case "raw":
case "string":
case "style":
case "transition":
case "xml":
result[ items [1]] = new R () {
ResourceType = items[1],
Identifier = itemName,
Id = value,
};
break;
case "styleable":
switch (items [0]) {
case "int":
result[ items [1]] = new R () {
ResourceType = items[1],
Identifier = itemName,
Id = Convert.ToInt32 (items [3], 10),
};
break;
case "int[]":
var arrayValues = items [3].Trim (new char [] { '{', '}' })
.Replace (" ", "")
.Split (new char [] { ',' });

result[ items [1]] = new R () {
ResourceType = items[1],
Type = RType.Array,
Identifier = itemName,
Ids = arrayValues.Select (x => string.IsNullOrEmpty (x) ? -1 : Convert.ToInt32 (x, 16)).ToArray (),
};
break;
}
break;
// for custom views
default:
result[ items [1]] = new R () {
ResourceType = items[1],
Identifier = itemName,
Id = value,
};
break;
}
}
}
}
}
18 changes: 18 additions & 0 deletions src/Xamarin.Android.Build.Tasks/Utilities/RtxtWriter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Linq;
using Microsoft.Android.Build.Tasks;
using Microsoft.Build.Utilities;

namespace Xamarin.Android.Tasks
{
/// Write a list of Item to a file
///
public class RtxtWriter {
public void Write (string file, Dictionary<string, R> items) {
File.WriteAllLines (file, items.Values.Select (x => x.ToString ()), Encoding.UTF8);
}
}
}

0 comments on commit 806f6ea

Please sign in to comment.