diff --git a/src/DynamoUtilities/Guid.cs b/src/DynamoUtilities/Guid.cs
index 284f9cb7061..f827896de35 100644
--- a/src/DynamoUtilities/Guid.cs
+++ b/src/DynamoUtilities/Guid.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
@@ -130,21 +131,79 @@ private static void SwapBytes(byte[] guid, int left, int right)
/// String representation of workspace after all elements' Guids replaced.
internal static string UpdateWorkspaceGUIDs(string jsonData)
{
- string pattern = @"([a-z0-9]{32})";
- string updatedJsonData = jsonData;
-
- // The unique collection of Guids
- var mc = Regex.Matches(jsonData, pattern)
- .Cast()
- .Select(m => m.Value)
- .Distinct();
-
- foreach (var match in mc)
+ const int numGuidChars = 32;
+ const char quote = '"';
+ const char backslash = '\\';
+
+ var dict = new Dictionary(StringComparer.OrdinalIgnoreCase);
+ var jsonBuilder = new StringBuilder(jsonData.Length);
+ var guidBuilder = new StringBuilder(numGuidChars);
+ bool lastWasEscape = false;
+ var totalGuidsInFile = 0;
+ for (int i = 0; i < jsonData.Length; i++)
{
- updatedJsonData = updatedJsonData.Replace(match, Guid.NewGuid().ToString("N"));
+ var c = jsonData[i];
+ jsonBuilder.Append(c);
+
+ if (c != quote)
+ {
+ // check if we have a backslash escape char
+ lastWasEscape = c == backslash;
+ continue;
+ }
+
+ // We don't care about \", as these are quotes inside other strings.
+ // This assumes that strings in the serialized json does not contain raw json
+ // with guids, those will be left intact. This might be the wrong assumption.
+ if (lastWasEscape)
+ {
+ lastWasEscape = false;
+ continue;
+ }
+
+ var count = 0;
+ // only iterate while we are finding hex letters and numbers (a-F0-9)
+ // as soon as we find anything else, we bail
+ while (i < jsonData.Length - 1)
+ {
+ c = jsonData[++i];
+ if (char.IsAsciiHexDigit(c))
+ {
+ guidBuilder.Append(c);
+ count++;
+ }
+ else
+ {
+ // if this is a quote char we want to reuse it on
+ // the next iteration of the for loop, so reset i
+ i--;
+ break;
+ }
+ }
+
+ // we have a guid between quotes, replace guidBuilder with a
+ // new guid, either a stored one from the dictionary, or a new one
+ if (c == quote && count == numGuidChars)
+ {
+ totalGuidsInFile++;
+ var oldGuid = guidBuilder.ToString();
+ guidBuilder.Clear();
+ if (!dict.TryGetValue(oldGuid, out var newGuid))
+ {
+ newGuid = Guid.NewGuid().ToString("N");
+ dict[oldGuid] = newGuid;
+ }
+ jsonBuilder.Append(newGuid);
+ }
+ // not a guid, add all guid builder chars to the json file
+ else if (count > 0)
+ {
+ jsonBuilder.Append(guidBuilder);
+ guidBuilder.Clear();
+ }
}
- return updatedJsonData;
+ return jsonBuilder.ToString();
}
}
}