mirror of
https://github.com/Thealexbarney/LibHac.git
synced 2024-11-14 10:49:41 +01:00
Adjust opened SaveDataInfoReaders if the collection is modified
This commit is contained in:
parent
f0aac13fab
commit
04b123f16e
4 changed files with 67 additions and 3 deletions
|
@ -227,7 +227,7 @@ namespace LibHac.Fs.Shim
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct SaveDataIterator
|
public struct SaveDataIterator : IDisposable
|
||||||
{
|
{
|
||||||
private FileSystemClient FsClient { get; }
|
private FileSystemClient FsClient { get; }
|
||||||
private ISaveDataInfoReader Reader { get; }
|
private ISaveDataInfoReader Reader { get; }
|
||||||
|
@ -259,5 +259,10 @@ namespace LibHac.Fs.Shim
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Reader?.Dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
namespace LibHac.FsService
|
namespace LibHac.FsService
|
||||||
{
|
{
|
||||||
public interface ISaveDataInfoReader
|
public interface ISaveDataInfoReader : IDisposable
|
||||||
{
|
{
|
||||||
Result ReadSaveDataInfo(out long readCount, Span<byte> saveDataInfoBuffer);
|
Result ReadSaveDataInfo(out long readCount, Span<byte> saveDataInfoBuffer);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using System.Linq;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using LibHac.Common;
|
using LibHac.Common;
|
||||||
|
@ -26,6 +27,7 @@ namespace LibHac.FsService
|
||||||
private bool IsKvdbLoaded { get; set; }
|
private bool IsKvdbLoaded { get; set; }
|
||||||
private ulong LastPublishedId { get; set; }
|
private ulong LastPublishedId { get; set; }
|
||||||
private int Version { get; set; }
|
private int Version { get; set; }
|
||||||
|
private List<SaveDataInfoReader> OpenedReaders { get; } = new List<SaveDataInfoReader>();
|
||||||
|
|
||||||
public SaveDataIndexer(FileSystemClient fsClient, string mountName, SaveDataSpaceId spaceId, ulong saveDataId)
|
public SaveDataIndexer(FileSystemClient fsClient, string mountName, SaveDataSpaceId spaceId, ulong saveDataId)
|
||||||
{
|
{
|
||||||
|
@ -356,6 +358,8 @@ namespace LibHac.FsService
|
||||||
|
|
||||||
var reader = new SaveDataInfoReader(this);
|
var reader = new SaveDataInfoReader(this);
|
||||||
|
|
||||||
|
OpenedReaders.Add(reader);
|
||||||
|
|
||||||
infoReader = reader;
|
infoReader = reader;
|
||||||
|
|
||||||
return Result.Success;
|
return Result.Success;
|
||||||
|
@ -490,10 +494,55 @@ namespace LibHac.FsService
|
||||||
|
|
||||||
private Result AdjustOpenedInfoReaders(ref SaveDataAttribute key)
|
private Result AdjustOpenedInfoReaders(ref SaveDataAttribute key)
|
||||||
{
|
{
|
||||||
// todo
|
// If a new key is added or removed during iteration of the list,
|
||||||
|
// make sure the current item of the iterator remains the same
|
||||||
|
|
||||||
|
// Todo: A more efficient way of doing this
|
||||||
|
List<SaveDataAttribute> list = KvDatabase.ToList().Select(x => x.key).ToList();
|
||||||
|
|
||||||
|
int index = list.BinarySearch(key);
|
||||||
|
|
||||||
|
bool keyWasAdded = index >= 0;
|
||||||
|
|
||||||
|
if (!keyWasAdded)
|
||||||
|
{
|
||||||
|
// If the item was not found, List<T>.BinarySearch returns a negative number that
|
||||||
|
// is the bitwise complement of the index of the next element that is larger than the item
|
||||||
|
index = ~index;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (SaveDataInfoReader reader in OpenedReaders)
|
||||||
|
{
|
||||||
|
if (keyWasAdded)
|
||||||
|
{
|
||||||
|
// New key was inserted before the iterator's position
|
||||||
|
// increment the position to compensate
|
||||||
|
if(reader.Position >= index)
|
||||||
|
{
|
||||||
|
reader.Position++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// The position should be decremented if the iterator's position is
|
||||||
|
// after the key that came directly after the deleted key
|
||||||
|
if (reader.Position > index)
|
||||||
|
{
|
||||||
|
reader.Position--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return Result.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void CloseReader(SaveDataInfoReader reader)
|
||||||
|
{
|
||||||
|
bool wasRemoved = OpenedReaders.Remove(reader);
|
||||||
|
|
||||||
|
Debug.Assert(wasRemoved);
|
||||||
|
}
|
||||||
|
|
||||||
private ref struct Mounter
|
private ref struct Mounter
|
||||||
{
|
{
|
||||||
private FileSystemClient FsClient { get; set; }
|
private FileSystemClient FsClient { get; set; }
|
||||||
|
@ -602,6 +651,11 @@ namespace LibHac.FsService
|
||||||
return Result.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Indexer?.CloseReader(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,6 +48,11 @@ namespace LibHac.FsService
|
||||||
|
|
||||||
return Result.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Reader?.Dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Explicit, Size = 0x50)]
|
[StructLayout(LayoutKind.Explicit, Size = 0x50)]
|
||||||
|
|
Loading…
Reference in a new issue