Tanoda
BitConverterGenerator.cs
Go to the documentation of this file.
1/******************************************************************************
2 * Copyright (C) Ultraleap, Inc. 2011-2020. *
3 * *
4 * Use subject to the terms of the Apache License 2.0 available at *
5 * http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
6 * between Ultraleap and you, your company or other organization. *
7 ******************************************************************************/
8
9using System;
10using System.IO;
11using System.Linq;
12using System.Reflection;
13using System.Runtime.InteropServices;
14using System.Collections.Generic;
15using UnityEngine;
16
18 using Query;
19
20 [CreateAssetMenu(menuName = "Generator/BitConverter", order = 900)]
22
23 public const string BEGIN_KEY = "//BEGIN";
24 public const string END_KEY = "//END";
25 public const string TO_KEY = "TO";
26 public const string GET_KEY = "GET";
27 public const string FILL_BYTES_KEY = "//FILL BYTES";
28
29 public TextAsset codeTemplate;
30 public TextAsset testTemplate;
31
34
35 public string[] primitiveTypes;
36
37 public override void Generate() {
38 generateCode();
39 generateUnitTests();
40 }
41
42 private void generateCode() {
43 List<string> lines = getLines(codeTemplate);
44 lines = lines.Select(l => l.Replace("Leap.Unity.Generation", "Leap.Unity").
45 Replace("BitConverterNonAlloc_Template_", "BitConverterNonAlloc")).
46 ToList();
47
48 using (var writer = File.CreateText(Path.Combine(targetFolder.Path, "BitConverterNonAlloc.cs"))) {
49 for (int i = 0; i < lines.Count; i++) {
50 string line = lines[i];
51
52 if (line.Contains(BEGIN_KEY)) {
53 List<string> methodTemplate = new List<string>();
54 while (true) {
55 i++;
56 string methodLine = lines[i];
57 if (methodLine.Contains(END_KEY)) {
58 break;
59 }
60 methodTemplate.Add(methodLine);
61 }
62
63 Func<int, string> byteExpr;
64 if (line.Contains(TO_KEY)) {
65 byteExpr = b => "_c.Byte" + b + " = bytes[offset++];";
66 } else if (line.Contains(GET_KEY)) {
67 byteExpr = b => "bytes[offset++] = _c.Byte" + b + ";";
68 } else {
69 throw new InvalidOperationException("Invalid template type [" + line + "]");
70 }
71
72 expandMethodTemplate(methodTemplate, writer, byteExpr);
73 } else {
74 writer.WriteLine(line);
75 }
76 }
77 }
78 }
79
80 private void expandMethodTemplate(List<string> methodTemplate, StreamWriter writer, Func<int, string> byteExpr) {
81 foreach (string primitiveType in primitiveTypes) {
82 Type type = Assembly.GetAssembly(typeof(int)).GetTypes().First(t => t.Name == primitiveType);
83
84 int bytes = Marshal.SizeOf(type);
85
86 for (int i = 0; i < methodTemplate.Count; i++) {
87 string line = methodTemplate[i];
88 line = line.Replace("Single", primitiveType);
89
90 if (line.Contains(FILL_BYTES_KEY)) {
91 string indent = new string(line.TakeWhile(c => char.IsWhiteSpace(c)).ToArray());
92 for (int j = 0; j < bytes; j++) {
93 writer.Write(indent);
94 writer.WriteLine(byteExpr(j));
95 }
96 } else {
97 writer.WriteLine(line);
98 }
99 }
100 }
101 }
102
103 private void generateUnitTests() {
104 List<string> lines = getLines(testTemplate);
105
106 lines = lines.Select(l => l.Replace("Leap.Unity.Generation", "Leap.Unity.Tests").
107 Replace("_Template_", "").
108 Replace("_BitConverterTestMock_", "BitConverterNonAlloc")).
109 ToList();
110
111 string codeTemplate = lines.Query().
112 SkipWhile(l => !l.Contains(BEGIN_KEY)).
113 Skip(1).
114 TakeWhile(l => !l.Contains(END_KEY)).
115 Select(s => s + "\n").
116 Fold((a, b) => a + b);
117
118 string beforeCode = lines.Query().
119 TakeWhile(l => !l.Contains(BEGIN_KEY)).
120 Select(s => s + "\n").
121 Fold((a, b) => a + b);
122
123 string afterCode = lines.Query().
124 SkipWhile(l => !l.Contains(END_KEY)).
125 Skip(1).
126 Select(s => s + "\n").
127 Fold((a, b) => a + b);
128
129 using (var writer = File.CreateText(Path.Combine(testFolder.Path, "BitConverterNonAllocTests.cs"))) {
130 writer.Write(beforeCode);
131
132 foreach (var primitiveType in primitiveTypes) {
133 //Replace Single with the actual primitive
134 //Also uncomment the Test attribute
135 writer.Write(codeTemplate.Replace("Single", primitiveType).
136 Replace("//[Test]", "[Test]"));
137 }
138
139 writer.Write(afterCode);
140 }
141 }
142
143 private List<string> getLines(TextAsset asset) {
144 List<string> lines = new List<string>();
145 using (var reader = new StringReader(asset.text)) {
146 while (true) {
147 string line = reader.ReadLine();
148 if (line == null) {
149 break;
150 }
151 lines.Add(line);
152 }
153 }
154 return lines;
155 }
156 }
157
158 public static class _BitConverterTestMock_ {
159 public static System.Single ToSingle(byte[] bytes, int offset) { return 0; }
160 public static void GetBytes(System.Single value, byte[] bytes, ref int offset) { return; }
161 }
162}
A convenient serializable representation of an asset folder. Only useful for editor scripts since ass...
Definition: AssetFolder.cs:26
virtual string Path
Gets or sets the folder path. This path will always be a path relative to the asset folder,...
Definition: AssetFolder.cs:43
A Query object is a type of immutable ordered collection of elements that can be used to perform usef...
Definition: Query.cs:90