anshdadhich commited on
Commit
7bb5463
·
verified ·
1 Parent(s): a012a68

Upload FastSeekWpf/Core/IndexStore.cs

Browse files
Files changed (1) hide show
  1. FastSeekWpf/Core/IndexStore.cs +48 -25
FastSeekWpf/Core/IndexStore.cs CHANGED
@@ -12,13 +12,14 @@ public class CachedEntry
12
  public ulong ParentRef { get; set; }
13
  public string Name { get; set; } = string.Empty;
14
  public FileKind Kind { get; set; }
 
15
  }
16
 
17
  [Serializable]
18
  public class CacheData
19
  {
20
  public List<CachedEntry> Entries { get; set; } = new();
21
- public string DriveRoot { get; set; } = string.Empty;
22
  public List<JournalCheckpoint> Checkpoints { get; set; } = new();
23
  }
24
 
@@ -31,6 +32,7 @@ public struct IndexEntry
31
  public ushort NameLen;
32
  public ushort NameLowerLen;
33
  public byte Flags;
 
34
 
35
  public readonly bool IsDir => (Flags & 1) != 0;
36
  public readonly FileKind Kind => IsDir ? FileKind.Directory : FileKind.File;
@@ -41,6 +43,7 @@ public struct IndexEntry
41
  /// - Arena-backed name storage (List&lt;byte&gt; for O(1) append)
42
  /// - Parallel cached lowercase strings for zero-allocation search
43
  /// - Sorted ref_lookup for O(log n) parent lookups
 
44
  /// </summary>
45
  public class IndexStore
46
  {
@@ -53,7 +56,8 @@ public class IndexStore
53
  public List<string> NameLowerCache = new();
54
  // Sorted by file_ref for binary search
55
  public List<(ulong fileRef, int idx)> RefLookup = new();
56
- public string DriveRoot = string.Empty;
 
57
  public List<JournalCheckpoint> Checkpoints = new();
58
 
59
  public int Count => Entries.Count;
@@ -62,6 +66,7 @@ public class IndexStore
62
 
63
  public string NameAt(int i) => NameCache[i];
64
  public string NameLowerAt(int i) => NameLowerCache[i];
 
65
 
66
  public uint? LookupIdx(ulong fileRef)
67
  {
@@ -88,18 +93,25 @@ public class IndexStore
88
 
89
  public void PopulateFromScan(ScanResult scan, string driveRoot)
90
  {
91
- DriveRoot = driveRoot;
 
 
 
 
 
 
 
 
 
 
 
 
92
  int count = scan.Records.Count;
93
- Entries.Clear();
94
- Entries.Capacity = count;
95
- NameArena.Clear();
96
- NameArena.Capacity = count * 30;
97
- NameLowerArena.Clear();
98
- NameLowerArena.Capacity = count * 30;
99
- NameCache.Clear();
100
- NameCache.Capacity = count;
101
- NameLowerCache.Clear();
102
- NameLowerCache.Capacity = count;
103
 
104
  foreach (var r in scan.Records)
105
  {
@@ -130,7 +142,8 @@ public class IndexStore
130
  NameLowerOff = nlOff,
131
  NameLen = nLen,
132
  NameLowerLen = nlLen,
133
- Flags = r.IsDir ? (byte)1 : (byte)0
 
134
  });
135
 
136
  NameCache.Add(name);
@@ -140,7 +153,6 @@ public class IndexStore
140
 
141
  /// <summary>
142
  /// Sort entries by lowercase name and rebuild lookup tables.
143
- /// (Renamed from Finalize to avoid CS0465 warning — object.Finalize is the destructor.)
144
  /// </summary>
145
  public void CompleteIndex()
146
  {
@@ -174,9 +186,10 @@ public class IndexStore
174
  FileRef = e.FileRef,
175
  ParentRef = e.ParentRef,
176
  Name = NameAt(i),
177
- Kind = e.Kind
 
178
  }).ToList(),
179
- DriveRoot = DriveRoot,
180
  Checkpoints = new List<JournalCheckpoint>(Checkpoints)
181
  };
182
  }
@@ -186,7 +199,7 @@ public class IndexStore
186
  int count = cache.Entries.Count;
187
  var store = new IndexStore
188
  {
189
- DriveRoot = cache.DriveRoot,
190
  Checkpoints = new List<JournalCheckpoint>(cache.Checkpoints)
191
  };
192
  store.Entries.Capacity = count;
@@ -216,7 +229,8 @@ public class IndexStore
216
  NameLowerOff = nlOff,
217
  NameLen = nLen,
218
  NameLowerLen = nlLen,
219
- Flags = c.Kind == FileKind.Directory ? (byte)1 : (byte)0
 
220
  });
221
 
222
  store.NameCache.Add(c.Name);
@@ -242,6 +256,11 @@ public class IndexStore
242
  ushort nlLen = (ushort)lowerBytes.Length;
243
  NameLowerArena.AddRange(lowerBytes);
244
 
 
 
 
 
 
245
  var entry = new IndexEntry
246
  {
247
  FileRef = record.FileRef,
@@ -250,7 +269,8 @@ public class IndexStore
250
  NameLowerOff = nlOff,
251
  NameLen = nLen,
252
  NameLowerLen = nlLen,
253
- Flags = record.Kind == FileKind.Directory ? (byte)1 : (byte)0
 
254
  };
255
 
256
  // Insert in sorted position by lowercase name
@@ -307,24 +327,27 @@ public class IndexStore
307
 
308
  public string BuildPath(ulong fileRef)
309
  {
310
- // string is a managed type, can't stackalloc it. Use small heap array.
311
  string[] components = new string[64];
312
  int compCount = 0;
313
  ulong current = fileRef;
 
314
 
315
  for (int i = 0; i < 64; i++)
316
  {
317
  var idx = LookupIdx(current);
318
  if (idx == null) break;
319
 
320
- var entry = Entries[(int)idx];
321
- components[compCount++] = NameAt((int)idx);
 
 
322
  if (entry.ParentRef == current) break;
323
  current = entry.ParentRef;
324
  }
325
 
326
- var sb = new StringBuilder(DriveRoot.Length + compCount * 32);
327
- sb.Append(DriveRoot);
 
328
  for (int i = compCount - 1; i >= 0; i--)
329
  {
330
  if (sb.Length > 0 && sb[sb.Length - 1] != '\\' && sb[sb.Length - 1] != '/')
 
12
  public ulong ParentRef { get; set; }
13
  public string Name { get; set; } = string.Empty;
14
  public FileKind Kind { get; set; }
15
+ public byte DriveIdx { get; set; }
16
  }
17
 
18
  [Serializable]
19
  public class CacheData
20
  {
21
  public List<CachedEntry> Entries { get; set; } = new();
22
+ public List<string> DriveRoots { get; set; } = new();
23
  public List<JournalCheckpoint> Checkpoints { get; set; } = new();
24
  }
25
 
 
32
  public ushort NameLen;
33
  public ushort NameLowerLen;
34
  public byte Flags;
35
+ public byte DriveIdx; // index into IndexStore.DriveRoots
36
 
37
  public readonly bool IsDir => (Flags & 1) != 0;
38
  public readonly FileKind Kind => IsDir ? FileKind.Directory : FileKind.File;
 
43
  /// - Arena-backed name storage (List&lt;byte&gt; for O(1) append)
44
  /// - Parallel cached lowercase strings for zero-allocation search
45
  /// - Sorted ref_lookup for O(log n) parent lookups
46
+ /// - Multi-drive support via per-entry DriveIdx
47
  /// </summary>
48
  public class IndexStore
49
  {
 
56
  public List<string> NameLowerCache = new();
57
  // Sorted by file_ref for binary search
58
  public List<(ulong fileRef, int idx)> RefLookup = new();
59
+ // One root per drive — entries reference via DriveIdx
60
+ public List<string> DriveRoots = new();
61
  public List<JournalCheckpoint> Checkpoints = new();
62
 
63
  public int Count => Entries.Count;
 
66
 
67
  public string NameAt(int i) => NameCache[i];
68
  public string NameLowerAt(int i) => NameLowerCache[i];
69
+ public string DriveRootAt(int i) => DriveRoots[Entries[i].DriveIdx];
70
 
71
  public uint? LookupIdx(ulong fileRef)
72
  {
 
93
 
94
  public void PopulateFromScan(ScanResult scan, string driveRoot)
95
  {
96
+ // Find or add drive root
97
+ byte driveIdx = 0;
98
+ int existing = DriveRoots.IndexOf(driveRoot);
99
+ if (existing >= 0)
100
+ {
101
+ driveIdx = (byte)existing;
102
+ }
103
+ else
104
+ {
105
+ driveIdx = (byte)DriveRoots.Count;
106
+ DriveRoots.Add(driveRoot);
107
+ }
108
+
109
  int count = scan.Records.Count;
110
+ Entries.Capacity = Math.Max(Entries.Capacity, Entries.Count + count);
111
+ NameArena.Capacity = Math.Max(NameArena.Capacity, NameArena.Count + count * 30);
112
+ NameLowerArena.Capacity = Math.Max(NameLowerArena.Capacity, NameLowerArena.Count + count * 30);
113
+ NameCache.Capacity = Math.Max(NameCache.Capacity, NameCache.Count + count);
114
+ NameLowerCache.Capacity = Math.Max(NameLowerCache.Capacity, NameLowerCache.Count + count);
 
 
 
 
 
115
 
116
  foreach (var r in scan.Records)
117
  {
 
142
  NameLowerOff = nlOff,
143
  NameLen = nLen,
144
  NameLowerLen = nlLen,
145
+ Flags = r.IsDir ? (byte)1 : (byte)0,
146
+ DriveIdx = driveIdx
147
  });
148
 
149
  NameCache.Add(name);
 
153
 
154
  /// <summary>
155
  /// Sort entries by lowercase name and rebuild lookup tables.
 
156
  /// </summary>
157
  public void CompleteIndex()
158
  {
 
186
  FileRef = e.FileRef,
187
  ParentRef = e.ParentRef,
188
  Name = NameAt(i),
189
+ Kind = e.Kind,
190
+ DriveIdx = e.DriveIdx
191
  }).ToList(),
192
+ DriveRoots = new List<string>(DriveRoots),
193
  Checkpoints = new List<JournalCheckpoint>(Checkpoints)
194
  };
195
  }
 
199
  int count = cache.Entries.Count;
200
  var store = new IndexStore
201
  {
202
+ DriveRoots = new List<string>(cache.DriveRoots),
203
  Checkpoints = new List<JournalCheckpoint>(cache.Checkpoints)
204
  };
205
  store.Entries.Capacity = count;
 
229
  NameLowerOff = nlOff,
230
  NameLen = nLen,
231
  NameLowerLen = nlLen,
232
+ Flags = c.Kind == FileKind.Directory ? (byte)1 : (byte)0,
233
+ DriveIdx = c.DriveIdx
234
  });
235
 
236
  store.NameCache.Add(c.Name);
 
256
  ushort nlLen = (ushort)lowerBytes.Length;
257
  NameLowerArena.AddRange(lowerBytes);
258
 
259
+ // Default to first drive if unknown
260
+ byte driveIdx = 0;
261
+ if (DriveRoots.Count == 0)
262
+ DriveRoots.Add("C:\\");
263
+
264
  var entry = new IndexEntry
265
  {
266
  FileRef = record.FileRef,
 
269
  NameLowerOff = nlOff,
270
  NameLen = nLen,
271
  NameLowerLen = nlLen,
272
+ Flags = record.Kind == FileKind.Directory ? (byte)1 : (byte)0,
273
+ DriveIdx = driveIdx
274
  };
275
 
276
  // Insert in sorted position by lowercase name
 
327
 
328
  public string BuildPath(ulong fileRef)
329
  {
 
330
  string[] components = new string[64];
331
  int compCount = 0;
332
  ulong current = fileRef;
333
+ byte driveIdx = 0;
334
 
335
  for (int i = 0; i < 64; i++)
336
  {
337
  var idx = LookupIdx(current);
338
  if (idx == null) break;
339
 
340
+ int eIdx = (int)idx;
341
+ components[compCount++] = NameAt(eIdx);
342
+ var entry = Entries[eIdx];
343
+ driveIdx = entry.DriveIdx;
344
  if (entry.ParentRef == current) break;
345
  current = entry.ParentRef;
346
  }
347
 
348
+ string driveRoot = driveIdx < DriveRoots.Count ? DriveRoots[driveIdx] : "C:\\";
349
+ var sb = new StringBuilder(driveRoot.Length + compCount * 32);
350
+ sb.Append(driveRoot);
351
  for (int i = compCount - 1; i >= 0; i--)
352
  {
353
  if (sb.Length > 0 && sb[sb.Length - 1] != '\\' && sb[sb.Length - 1] != '/')