Skip to content

Commit 16354a5

Browse files
author
Aswin Gopal
committed
Update the parser to preserve original and re-write only if changes in processors are required.
1 parent d790fd9 commit 16354a5

File tree

1 file changed

+156
-56
lines changed

1 file changed

+156
-56
lines changed

Packages/com.unity.inputsystem/InputSystem/Actions/InputActionAsset.cs

Lines changed: 156 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1014,87 +1014,187 @@ internal void MigrateJson(ref ReadFileJson parsedJson)
10141014
{
10151015
if (parsedJson.version >= JsonVersion.Version1)
10161016
return;
1017-
1018-
if ((parsedJson.maps?.Length ?? 0) > 0 && parsedJson.version < JsonVersion.Version1)
1017+
1018+
var maps = parsedJson.maps;
1019+
if (maps == null || maps.Length == 0)
10191020
{
1020-
for (var mi = 0; mi < parsedJson.maps.Length; ++mi)
1021+
parsedJson.version = JsonVersion.Version1;
1022+
return;
1023+
}
1024+
1025+
for (int mi = 0; mi < maps.Length; mi++)
1026+
{
1027+
var mapJson = maps[mi];
1028+
if (mapJson.actions == null || mapJson.actions.Length == 0)
1029+
continue;
1030+
1031+
for (int ai = 0; ai < mapJson.actions.Length; ai++)
10211032
{
1022-
var mapJson = parsedJson.maps[mi];
1023-
if (mapJson.actions == null || mapJson.actions.Length == 0)
1033+
var actionJson = mapJson.actions[ai];
1034+
var processors = actionJson.processors;
1035+
if (string.IsNullOrEmpty(processors))
1036+
continue;
1037+
1038+
// Find top-level ';' token ranges without altering whitespace.
1039+
var tokenRanges = new List<(int start, int length)>();
1040+
{
1041+
int depth = 0, tokenStart = 0;
1042+
for (int i = 0; i < processors.Length; i++)
1043+
{
1044+
char c = processors[i];
1045+
if (c == '(')
1046+
depth++;
1047+
else if (c == ')')
1048+
depth = Math.Max(0, depth - 1);
1049+
else if (c == ';' && depth == 0)
1050+
{
1051+
int len = i - tokenStart;
1052+
if (len > 0)
1053+
tokenRanges.Add((tokenStart, len));
1054+
1055+
tokenStart = i + 1;
1056+
}
1057+
}
1058+
if (tokenStart < processors.Length)
1059+
{
1060+
int len = processors.Length - tokenStart;
1061+
if (len > 0)
1062+
tokenRanges.Add((tokenStart, len));
1063+
}
1064+
}
1065+
1066+
if (tokenRanges.Count == 0)
10241067
continue;
1025-
for (var ai = 0; ai < mapJson.actions.Length; ++ai)
1068+
1069+
bool anyTokenChanged = false;
1070+
var rebuilt = new System.Text.StringBuilder(processors.Length + 16);
1071+
int cursor = 0;
1072+
1073+
foreach (var (start, length) in tokenRanges)
10261074
{
1027-
var actionJson = mapJson.actions[ai];
1028-
var raw = actionJson.processors;
1029-
if (string.IsNullOrEmpty(raw))
1075+
if (start > cursor)
1076+
rebuilt.Append(processors, cursor, start - cursor);
1077+
1078+
var tokenText = processors.Substring(start, length);
1079+
var trimmed = tokenText.Trim();
1080+
1081+
// If we can't parse, just write the original token back unchanged.
1082+
NameAndParameters nap;
1083+
try
1084+
{
1085+
nap = NameAndParameters.Parse(trimmed);
1086+
}
1087+
catch
1088+
{
1089+
rebuilt.Append(tokenText);
1090+
cursor = start + length;
10301091
continue;
1092+
}
10311093

1032-
var originalTokens = raw.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries).Select(t => t.Trim()).ToList();
1094+
var procType = InputSystem.TryGetProcessor(nap.name);
1095+
if (procType == null || nap.parameters.Count == 0)
1096+
{
1097+
rebuilt.Append(tokenText);
1098+
cursor = start + length;
1099+
continue;
1100+
}
10331101

1034-
List<NameAndParameters> parsed = null;
1035-
NameAndParameters.ParseMultiple(raw, ref parsed);
1036-
if (parsed == null || parsed.Count == 0)
1102+
var enumFields = procType.GetFields(BindingFlags.Public | BindingFlags.Instance).Where(f => f.FieldType.IsEnum).ToArray();
1103+
if (enumFields.Length == 0)
1104+
{
1105+
rebuilt.Append(tokenText);
1106+
cursor = start + length;
10371107
continue;
1108+
}
10381109

1039-
var canPreservePerToken = parsed.Count == originalTokens.Count;
1040-
var rebuiltTokens = canPreservePerToken ? new List<string>(originalTokens) : new List<string>(parsed.Count);
1041-
var anyProcessorChanged = false;
1110+
int leadingWs = tokenText.Length - tokenText.TrimStart().Length;
1111+
int trailingWs = tokenText.Length - tokenText.TrimEnd().Length;
1112+
string core = tokenText.Substring(leadingWs, tokenText.Length - leadingWs - trailingWs);
10421113

1043-
for (int pi = 0; pi < parsed.Count; pi++)
1114+
bool changedThisToken = false;
1115+
1116+
foreach (var field in enumFields)
10441117
{
1045-
var nap = parsed[pi];
1046-
var procType = InputSystem.TryGetProcessor(nap.name);
1047-
if (procType == null || nap.parameters.Count == 0)
1048-
{
1049-
if (!canPreservePerToken)
1050-
rebuiltTokens.Add(nap.ToString());
1118+
if (core.IndexOf(field.Name + "=", StringComparison.Ordinal) < 0)
10511119
continue;
1052-
}
10531120

1054-
var dict = nap.parameters.ToDictionary(p => p.name, p => p.value.ToString());
1055-
var changedThisProcessor = false;
1121+
// Map ordinal -> underlying numeric values for the enum.
1122+
var values = Enum.GetValues(field.FieldType);
1123+
var numeric = new int[values.Length];
1124+
for (int i = 0; i < values.Length; i++)
1125+
numeric[i] = Convert.ToInt32(values.GetValue(i));
10561126

1057-
// For each enum parameter, if value is an ordinal index, replace with the underlying numeric enum value.
1058-
foreach (var field in procType.GetFields(BindingFlags.Public | BindingFlags.Instance).Where(f => f.FieldType.IsEnum))
1127+
// Replace occurrences of "<Field>=<int>".
1128+
int search = 0;
1129+
while (true)
10591130
{
1060-
if (dict.TryGetValue(field.Name, out var ordStr) && int.TryParse(ordStr, out var ordinal))
1131+
int hit = core.IndexOf(field.Name + "=", search, StringComparison.Ordinal);
1132+
if (hit < 0) break;
1133+
1134+
int valStart = hit + field.Name.Length + 1;
1135+
int j = valStart;
1136+
bool neg = false;
1137+
if (j < core.Length && core[j] == '-')
10611138
{
1062-
var values = Enum.GetValues(field.FieldType).Cast<object>().ToArray();
1063-
if (ordinal >= 0 && ordinal < values.Length)
1064-
{
1065-
dict[field.Name] = Convert.ToInt32(values[ordinal]).ToString();
1066-
changedThisProcessor = true;
1067-
}
1139+
neg = true;
1140+
j++;
10681141
}
1069-
}
10701142

1071-
if (!changedThisProcessor)
1072-
{
1073-
if (!canPreservePerToken)
1074-
rebuiltTokens.Add(nap.ToString());
1075-
}
1076-
else
1077-
{
1078-
// Rebuild only this processor’s text.
1079-
var paramText = string.Join(",", dict.Select(kv => $"{kv.Key}={kv.Value}"));
1080-
var migrated = $"{nap.name}({paramText})";
1143+
int valEnd = j;
1144+
while (valEnd < core.Length && char.IsDigit(core[valEnd]))
1145+
valEnd++;
10811146

1082-
if (canPreservePerToken)
1083-
rebuiltTokens[pi] = migrated;
1084-
else
1085-
rebuiltTokens.Add(migrated);
1147+
if (valEnd == j)
1148+
{
1149+
search = valStart;
1150+
continue;
1151+
}
10861152

1087-
anyProcessorChanged = true;
1153+
var numStr = core.Substring(valStart, valEnd - valStart);
1154+
if (int.TryParse(neg ? "-" + numStr : numStr, out var parsed))
1155+
{
1156+
if (parsed >= 0 && parsed < numeric.Length)
1157+
{
1158+
int underlying = numeric[parsed];
1159+
if (underlying != parsed)
1160+
{
1161+
core = core.Substring(0, valStart) + underlying.ToString() + core.Substring(valEnd);
1162+
changedThisToken = true;
1163+
search = valStart + underlying.ToString().Length;
1164+
continue;
1165+
}
1166+
}
1167+
}
1168+
1169+
search = valEnd;
10881170
}
10891171
}
10901172

1091-
// Only touch the processors string if something actually changed.
1092-
if (anyProcessorChanged)
1093-
actionJson.processors = string.Join(";", rebuiltTokens);
1094-
mapJson.actions[ai] = actionJson;
1173+
if (changedThisToken)
1174+
{
1175+
anyTokenChanged = true;
1176+
rebuilt.Append(tokenText.Substring(0, leadingWs));
1177+
rebuilt.Append(core);
1178+
rebuilt.Append(tokenText.Substring(tokenText.Length - trailingWs, trailingWs));
1179+
}
1180+
else
1181+
{
1182+
rebuilt.Append(tokenText);
1183+
}
1184+
1185+
cursor = start + length;
10951186
}
1096-
parsedJson.maps[mi] = mapJson;
1187+
1188+
if (cursor < processors.Length)
1189+
rebuilt.Append(processors, cursor, processors.Length - cursor);
1190+
1191+
if (anyTokenChanged)
1192+
actionJson.processors = rebuilt.ToString();
1193+
1194+
mapJson.actions[ai] = actionJson;
10971195
}
1196+
1197+
maps[mi] = mapJson;
10981198
}
10991199
// Bump the version so we never re-migrate
11001200
parsedJson.version = JsonVersion.Version1;

0 commit comments

Comments
 (0)