/// <summary> /// Get the index of the name in the sorted folder entries list /// </summary> /// <param name="name">The name to search for in the entries</param> /// <returns> /// The zero based index of the entry if found; /// otherwise, a negative number that is the bitwise complement of the index of the next element that is larger than item or, /// if there is no larger element, the bitwise complement of this.entries.ObjectsUsed. /// </returns> private int GetSortedEntriesIndexOfName(LazyUTF8String name) { if (this.sortedEntries.Count == 0) { return(-1); } // Insertions are almost always at the end, because the inputs are pre-sorted by git. // We only have to insert at a different spot where Windows/Mac and git disagree on the sort order; // on Linux we use a case-sensitive comparsion, which we expect to align with git. bool caseSensitive = GVFSPlatform.Instance.Constants.CaseSensitiveFileSystem; int compareResult = this.sortedEntries[this.sortedEntries.Count - 1].Name.Compare(name, caseSensitive); if (compareResult == 0) { return(this.sortedEntries.Count - 1); } else if (compareResult < 0) { return(~this.sortedEntries.Count); } int left = 0; int right = this.sortedEntries.Count - 2; while (right - left > 2) { int middle = left + ((right - left) / 2); int comparison = this.sortedEntries[middle].Name.Compare(name, caseSensitive); if (comparison == 0) { return(middle); } if (comparison < 0) { left = middle + 1; } else { right = middle - 1; } } for (int i = right; i >= left; i--) { compareResult = this.sortedEntries[i].Name.Compare(name, caseSensitive); if (compareResult == 0) { return(i); } else if (compareResult < 0) { return(~(i + 1)); } } return(~left); }
public static unsafe LazyUTF8String FromByteArray(byte *bufferPtr, int length) { bytePool.MakeFreeSpace(length); LazyUTF8String lazyString = stringPool.GetNew(); byte *poolPtrForLoop = bytePool.RawPointer + bytePool.FreeIndex; byte *bufferPtrForLoop = bufferPtr; int index = 0; while (index < length) { if (*bufferPtrForLoop <= 127) { *poolPtrForLoop = *bufferPtrForLoop; } else { // The string has non-ASCII characters in it, fall back to full parsing lazyString.SetToString(Encoding.UTF8.GetString(bufferPtr, length)); return(lazyString); } ++poolPtrForLoop; ++bufferPtrForLoop; ++index; } lazyString.ResetState(bytePool.FreeIndex, length); bytePool.AdvanceFreeIndex(length); return(lazyString); }
public unsafe void ExpandAfterShrinkPool_AllocatesDefault() { LazyUTF8String.ResetPool(new MockTracer(), DefaultIndexEntryCount); string fileAndFolderNames = "folderSDKfile.txtDKfolders"; UseASCIIBytePointer( fileAndFolderNames, bufferPtr => { int initialBytePoolSize = LazyUTF8String.BytePoolSize(); int initialStringPoolSize = LazyUTF8String.StringPoolSize(); LazyUTF8String.FromByteArray(bufferPtr + 6, 3); LazyUTF8String.FromByteArray(bufferPtr + 17, 2); LazyUTF8String.ShrinkPool(); CheckPoolSizes(expectedBytePoolSize: 6, expectedStringPoolSize: 2); LazyUTF8String.FreePool(); CheckPoolSizes(expectedBytePoolSize: 6, expectedStringPoolSize: 2); LazyUTF8String.ShrinkPool(); CheckPoolSizes(expectedBytePoolSize: 0, expectedStringPoolSize: 0); LazyUTF8String.FromByteArray(bufferPtr + 6, 3); CheckPoolSizes(expectedBytePoolSize: initialBytePoolSize, expectedStringPoolSize: initialStringPoolSize); LazyUTF8String.ShrinkPool(); CheckPoolSizes(expectedBytePoolSize: 3, expectedStringPoolSize: 1); }); }
public void AddItemAtEnd() { SortedFolderEntries sfe = SetupDefaultEntries(); LazyUTF8String name = ConstructLazyUTF8String("{{shouldbeattheend"); sfe.AddFolder(name); sfe[defaultFiles.Length + defaultFolders.Length].Name.ShouldEqual(name, "Item added at incorrect index."); }
private static void AddFolders(SortedFolderEntries entries, params string[] names) { for (int i = 0; i < names.Length; i++) { LazyUTF8String entryString = ConstructLazyUTF8String(names[i]); entries.AddFolder(entryString); } }
private FolderData InsertFolder(LazyUTF8String name, int insertionIndex) { FolderData data = folderPool.GetNew(); data.ResetData(name); this.sortedEntries.Insert(insertionIndex, data); return(data); }
public void EntryFoundDifferentCase() { SortedFolderEntries sfe = SetupDefaultEntries(); LazyUTF8String findName = ConstructLazyUTF8String("Folder"); sfe.TryGetValue(findName, out FolderEntryData folderEntryData).ShouldBeTrue(); folderEntryData.ShouldNotBeNull(); }
public void EntryNotFound() { SortedFolderEntries sfe = SetupDefaultEntries(); LazyUTF8String findName = ConstructLazyUTF8String("Anything"); sfe.TryGetValue(findName, out FolderEntryData folderEntryData).ShouldBeFalse(); folderEntryData.ShouldBeNull(); }
private FileData InsertFile(LazyUTF8String name, byte[] shaBytes, int insertionIndex) { FileData data = filePool.GetNew(); data.ResetData(name, shaBytes); this.sortedEntries.Insert(insertionIndex, data); return(data); }
private static unsafe LazyUTF8String ConstructLazyUTF8String(string name) { byte[] buffer = Encoding.ASCII.GetBytes(name); fixed(byte *bufferPtr = buffer) { return(LazyUTF8String.FromByteArray(bufferPtr, name.Length)); } }
public void FoldersShouldBeIncludedWhenSparseFolderDataIsEmpty() { SortedFolderEntries sfe = SetupDefaultEntries(); LazyUTF8String name = ConstructLazyUTF8String("IsIncludedFalse"); sfe.GetOrAddFolder(new[] { name }, partIndex: 0, parentIsIncluded: false, rootSparseFolderData: new SparseFolderData()); ValidateFolder(sfe, name, isIncludedValue: true); }
public void AddItemAtEnd() { SortedFolderEntries sfe = SetupDefaultEntries(); LazyUTF8String name = ConstructLazyUTF8String("{{shouldbeattheend"); sfe.AddFile(name, new byte[20]); sfe[GetDefaultEntriesLength()].Name.ShouldEqual(name, "Item added at incorrect index."); }
public void AddItemAtTheBeginning() { SortedFolderEntries sfe = SetupDefaultEntries(); LazyUTF8String name = ConstructLazyUTF8String("((shouldbeatthestart"); sfe.AddFile(name, new byte[20]); sfe[0].Name.ShouldEqual(name, "Item added at incorrect index."); }
/// <summary> /// Get the index of the name in the sorted folder entries list /// </summary> /// <param name="name">The name to search for in the entries</param> /// <returns> /// The zero based index of the entry if found; /// otherwise, a negative number that is the bitwise complement of the index of the next element that is larger than item or, /// if there is no larger element, the bitwise complement of this.entries.ObjectsUsed. /// </returns> private int GetSortedEntriesIndexOfName(LazyUTF8String name) { if (this.sortedEntries.Count == 0) { return(-1); } // Insertions are almost always at the end, because the inputs are pre-sorted by git. // We only have to insert at a different spot where Windows and git disagree on the sort order. int compareResult = this.sortedEntries[this.sortedEntries.Count - 1].Name.CaseInsensitiveCompare(name); if (compareResult == 0) { return(this.sortedEntries.Count - 1); } else if (compareResult < 0) { return(~this.sortedEntries.Count); } int left = 0; int right = this.sortedEntries.Count - 2; while (right - left > 2) { int middle = left + ((right - left) / 2); int comparison = this.sortedEntries[middle].Name.CaseInsensitiveCompare(name); if (comparison == 0) { return(middle); } if (comparison < 0) { left = middle + 1; } else { right = middle - 1; } } for (int i = right; i >= left; i--) { compareResult = this.sortedEntries[i].Name.CaseInsensitiveCompare(name); if (compareResult == 0) { return(i); } else if (compareResult < 0) { return(~(i + 1)); } } return(~left); }
private static void AddFolders(SortedFolderEntries entries, params string[] names) { for (int i = 0; i < names.Length; i++) { LazyUTF8String entryString = ConstructLazyUTF8String(names[i]); entries.GetOrAddFolder(new[] { entryString }, partIndex: 0, parentIsIncluded: true, rootSparseFolderData: new SparseFolderData()); ValidateFolder(entries, entryString, isIncludedValue: true); } }
public void AddFolderWhereParentIncludedIsTrueAndChildIsNotIncluded() { SortedFolderEntries sfe = SetupDefaultEntries(); LazyUTF8String name = ConstructLazyUTF8String("ChildNotIncluded"); SparseFolderData sparseFolderData = new SparseFolderData(); sparseFolderData.Children.Add("Child", new SparseFolderData()); sfe.GetOrAddFolder(new[] { name }, partIndex: 0, parentIsIncluded: true, rootSparseFolderData: sparseFolderData); ValidateFolder(sfe, name, isIncludedValue: false); }
public void MinimumPoolSize() { LazyUTF8String.ResetPool(new MockTracer(), 0); LazyUTF8String.FreePool(); LazyUTF8String.BytePoolSize().ShouldBeAtLeast(1); LazyUTF8String.InitializePools(new MockTracer(), 0); LazyUTF8String.BytePoolSize().ShouldBeAtLeast(1); }
public unsafe void CaseInsensitiveEquals_OneNameShorterEqualsFalse() { UseASCIIBytePointer( "folderonefile.txtFold", bufferPtr => { LazyUTF8String firstFolder = LazyUTF8String.FromByteArray(bufferPtr + 0, 6); LazyUTF8String secondFolder = LazyUTF8String.FromByteArray(bufferPtr + 17, 4); firstFolder.CaseInsensitiveEquals(secondFolder).ShouldBeFalse(nameof(firstFolder.CaseInsensitiveEquals)); }); }
public void AddFolderBelowTopLevelNotIncluded() { SortedFolderEntries sfe = SetupDefaultEntries(); LazyUTF8String name = ConstructLazyUTF8String("Child"); LazyUTF8String name2 = ConstructLazyUTF8String("GrandChild"); SparseFolderData sparseFolderData = new SparseFolderData(); sparseFolderData.Children.Add("Child", new SparseFolderData()); sfe.GetOrAddFolder(new[] { name, name2 }, partIndex: 1, parentIsIncluded: true, rootSparseFolderData: sparseFolderData); ValidateFolder(sfe, name2, isIncludedValue: false); }
public unsafe void CaseInsensitiveCompare_EqualsGreaterThanZero2() { UseASCIIBytePointer( "folderSDKfile.txtDKfolders", bufferPtr => { LazyUTF8String firstFolder = LazyUTF8String.FromByteArray(bufferPtr + 6, 3); LazyUTF8String secondFolder = LazyUTF8String.FromByteArray(bufferPtr + 17, 2); firstFolder.CaseInsensitiveCompare(secondFolder).ShouldBeAtLeast(1, nameof(firstFolder.CaseInsensitiveCompare)); }); }
private static void AddFiles(SortedFolderEntries entries, params string[] names) { for (int i = 0; i < names.Length; i++) { LazyUTF8String entryString = ConstructLazyUTF8String(names[i]); entries.AddFile(entryString, new byte[20]); entries.TryGetValue(entryString, out FolderEntryData folderEntryData).ShouldBeTrue(); folderEntryData.ShouldNotBeNull(); folderEntryData.IsFolder.ShouldBeFalse(); } }
public unsafe void CaseInsensitiveCompare_EqualsLessThanZero() { UseASCIIBytePointer( "folderonefile.txtfolders", bufferPtr => { LazyUTF8String firstFolder = LazyUTF8String.FromByteArray(bufferPtr + 0, 6); LazyUTF8String secondFolder = LazyUTF8String.FromByteArray(bufferPtr + 17, 7); firstFolder.CaseInsensitiveCompare(secondFolder).ShouldBeAtMost(-1, nameof(firstFolder.CaseInsensitiveCompare)); }); }
public FolderData GetOrAddFolder(LazyUTF8String name) { int index = this.GetSortedEntriesIndexOfName(name); if (index >= 0) { return((FolderData)this.sortedEntries[index]); } return(this.InsertFolder(name, ~index)); }
public unsafe void CaseInsensitiveEquals_SameNameDifferentCase2_EqualsTrue() { UseASCIIBytePointer( "FOlderonefile.txtFolder", bufferPtr => { LazyUTF8String firstFolder = LazyUTF8String.FromByteArray(bufferPtr + 0, 6); LazyUTF8String secondFolder = LazyUTF8String.FromByteArray(bufferPtr + 17, 6); firstFolder.CaseInsensitiveEquals(secondFolder).ShouldBeTrue(nameof(firstFolder.CaseInsensitiveEquals)); }); }
public unsafe void NonASCIICharacters_Compare() { UseUTF8BytePointer( "folderSDKfile.txtريلٌأكتوبرDKfolders", bufferPtr => { LazyUTF8String firstFolder = LazyUTF8String.FromByteArray(bufferPtr + 6, 3); LazyUTF8String secondFolder = LazyUTF8String.FromByteArray(bufferPtr + 17, 20); firstFolder.CaseInsensitiveCompare(secondFolder).ShouldBeAtMost(-1, nameof(firstFolder.CaseInsensitiveCompare)); }); }
public void ResetData(LazyUTF8String name) { this.Name = name; this.ChildrenHaveSizes = false; if (this.ChildEntries == null) { this.ChildEntries = new SortedFolderEntries(); } this.ChildEntries.Clear(); }
private static void ValidateFolder(SortedFolderEntries entries, LazyUTF8String entryToValidate, bool isIncludedValue) { entries.TryGetValue(entryToValidate, out FolderEntryData folderEntryData).ShouldBeTrue(); folderEntryData.ShouldNotBeNull(); folderEntryData.IsFolder.ShouldBeTrue(); FolderData folderData = folderEntryData as FolderData; folderData.ShouldNotBeNull(); folderData.IsIncluded.ShouldEqual(isIncludedValue, "IsIncluded does not match expected value."); }
public unsafe void PoolSizeCheck() { UseASCIIBytePointer( "folderSDKfile.txtDKfolders", bufferPtr => { int bytePoolSizeBeforeFreePool = LazyUTF8String.BytePoolSize(); int stringPoolSizeBeforeFreePool = LazyUTF8String.StringPoolSize(); LazyUTF8String firstFolder = LazyUTF8String.FromByteArray(bufferPtr + 6, 3); LazyUTF8String secondFolder = LazyUTF8String.FromByteArray(bufferPtr + 17, 2); CheckPoolSizes(bytePoolSizeBeforeFreePool, stringPoolSizeBeforeFreePool); }); }
public bool TryGetValue(LazyUTF8String name, out FolderEntryData value) { int index = this.GetSortedEntriesIndexOfName(name); if (index >= 0) { value = this.sortedEntries[index]; return(true); } value = null; return(false); }
public unsafe void GetString() { UseASCIIBytePointer( "folderonefile.txt", bufferPtr => { LazyUTF8String firstFolder = LazyUTF8String.FromByteArray(bufferPtr + 0, 6); firstFolder.GetString().ShouldEqual("folder"); LazyUTF8String secondFolder = LazyUTF8String.FromByteArray(bufferPtr + 6, 3); secondFolder.GetString().ShouldEqual("one"); LazyUTF8String file = LazyUTF8String.FromByteArray(bufferPtr + 9, 8); file.GetString().ShouldEqual("file.txt"); }); }