Browse Source

Use KMP algorithm for loading scene data

habeebweeb 4 years ago
parent
commit
89960886d2

+ 5 - 1
MultipleMaids/CM3D2/MultipleMaids/Plugin/MultipleMaids.Gui.cs

@@ -9178,7 +9178,11 @@ namespace CM3D2.MultipleMaids.Plugin
                         , imageHeight), saveScenes[i].screenshot, saveImageStyle))
                     {
                         selectedSave = i;
-                        manageSaveFlag = true;
+                        ReadScene();
+                        if (sceneData != null)
+                        {
+                            manageSaveFlag = true;
+                        }
                     }
 
                     i--;

+ 35 - 42
MultipleMaids/SaveManager.cs

@@ -11,6 +11,7 @@ namespace CM3D2.MultipleMaids.Plugin
     public partial class MultipleMaids
     {
         private static readonly byte[] pngEnd = Encoding.ASCII.GetBytes("IEND");
+        internal static readonly int[] border = { -1, 0, 0, 0, 0 };
         private static string sceneData;
         private const string baseDirectoryName = "< Base Directory >";
         private string saveScenePath = Path.Combine(Path.GetFullPath(".\\"), "Mod\\MultipleMaidsSave");
@@ -119,44 +120,8 @@ namespace CM3D2.MultipleMaids.Plugin
             InitializeSaveList();
         }
 
-        private void LoadSave()
+        private void LoadScene()
         {
-            string filePath = saveScenes[selectedSave].info.FullName;
-            if (!File.Exists(filePath))
-            {
-                InitializeSaveList();
-                sceneData = null;
-                return;
-            }
-
-            using (FileStream fileStream = File.OpenRead(filePath))
-            {
-                byte[] buffer = new byte[pngEnd.Length];
-                long position = 0;
-
-                while (true)
-                {
-                    int bytesRead = fileStream.Read(buffer, 0, buffer.Length);
-
-                    if (bytesRead != pngEnd.Length)
-                    {
-                        sceneData = null;
-                        return;
-                    }
-
-                    if (BytesEqual(buffer, pngEnd))
-                    {
-                        fileStream.Position += 4;
-                        break;
-                    }
-
-                    fileStream.Position = ++position;
-                }
-                using (MemoryStream sceneStream = LZMA.Decompress(fileStream))
-                {
-                    sceneData = Encoding.Unicode.GetString(sceneStream.ToArray());
-                }
-            }
             SavePng temp = saveScenes[selectedSave];
             FileSystemInfo info = temp.info;
             info.LastWriteTime = info.LastAccessTime = DateTime.Now;
@@ -282,16 +247,44 @@ namespace CM3D2.MultipleMaids.Plugin
             selectedSave = saveScenes.Count - 1;
         }
 
-        private static bool BytesEqual(byte[] a, byte[] b)
+        private void ReadScene()
         {
-            if (a.Length != b.Length) return false;
+            string filePath = saveScenes[selectedSave].info.FullName;
+            if (!File.Exists(filePath))
+            {
+                RefreshSaveManager();
+                sceneData = null;
+                return;
+            }
 
-            for (int i = 0; i < a.Length; i++)
+            using (FileStream fileStream = File.OpenRead(filePath))
             {
-                if (a[i] != b[i]) return false;
+                long bytesRead = 0;
+                int j = 0;
+                int b;
+
+                while ((b = fileStream.ReadByte()) != -1)
+                {
+                    bytesRead++;
+                    while (j >= 0 && b != pngEnd[j])
+                    {
+                        j = border[j];
+                    }
+
+                    if (++j == pngEnd.Length)
+                    {
+                        fileStream.Position += 4;
+                        using (MemoryStream sceneStream = LZMA.Decompress(fileStream))
+                        {
+                            sceneData = Encoding.Unicode.GetString(sceneStream.ToArray());
+                            return;
+                        }
+                    }
+                }
+                sceneData = null;
             }
-            return true;
         }
+
         class SavePng
         {
             public FileInfo info { get; }