Example #1
0
        /// <summary>Try to read everything up to the given <paramref name="delimiter"/>, ignoring delimiters that are
        /// preceded by <paramref name="delimiterEscape"/>.</summary>
        /// <param name="span">The read data, if any.</param>
        /// <param name="delimiter">The delimiter to look for.</param>
        /// <param name="delimiterEscape">If found prior to <paramref name="delimiter"/> it will skip that occurrence.</param>
        /// <param name="advancePastDelimiter">True to move past the <paramref name="delimiter"/> if found.</param>
        /// <returns>True if the <paramref name="delimiter"/> was found.</returns>
        public bool TryReadTo(out ReadOnlySpan <byte> span, byte delimiter, byte delimiterEscape, bool advancePastDelimiter = true)
        {
            ReadOnlySpan <byte> remaining = UnreadSpan;

#if NET
            int index = remaining.IndexOf(delimiter);
#else
            int index = SpanHelpers.IndexOf(ref MemoryMarshal.GetReference(remaining), delimiter, remaining.Length);
#endif

            if ((index > 0 && remaining[index - 1] != delimiterEscape) || 0u >= (uint)index)
            {
                span = remaining.Slice(0, index);
                AdvanceCurrentSpan(index + (advancePastDelimiter ? 1 : 0));
                return(true);
            }

            // This delimiter might be skipped, go down the slow path
            return(TryReadToSlow(out span, delimiter, delimiterEscape, index, advancePastDelimiter));
        }
Example #2
0
        public static void WriteMachineEndian <T>(Span <byte> buffer, ref T value)
            where T : struct
        {
#if netstandard
            if (SpanHelpers.IsReferenceOrContainsReferences <T>())
            {
                ThrowHelper.ThrowArgumentException_InvalidTypeWithPointersNotSupported(typeof(T));
            }
#else
            if (RuntimeHelpers.IsReferenceOrContainsReferences <T>())
            {
                throw new ArgumentException(SR.Format(SR.Argument_InvalidTypeWithPointersNotSupported, typeof(T)));
            }
#endif
            if ((uint)Unsafe.SizeOf <T>() > (uint)buffer.Length)
            {
                throw new ArgumentOutOfRangeException();
            }
            Unsafe.WriteUnaligned <T>(ref buffer.DangerousGetPinnableReference(), value);
        }
Example #3
0
        public void TestAllignmentMatchLastIndexOf_Byte()
        {
            byte[] array = new byte[4 * Vector <byte> .Count];
            for (int i = 0; i < array.Length; i++)
            {
                array[i] = 5;
            }
            for (var i = 0; i < Vector <byte> .Count; i++)
            {
                var span = new Span <byte>(array, i, 3 * Vector <byte> .Count);
                //int idx = span.LastIndexOf<byte>(5);
                int idx = SpanHelpers.FindLastIndex(ref MemoryMarshal.GetReference(span), x => x == 5, span.Length);
                Assert.Equal(span.Length - 1, idx);

                span = new Span <byte>(array, i, 3 * Vector <byte> .Count - 3);
                //idx = span.LastIndexOf<byte>(5);
                idx = SpanHelpers.FindLastIndex(ref MemoryMarshal.GetReference(span), x => x == 5, span.Length);
                Assert.Equal(span.Length - 1, idx);
            }
        }
Example #4
0
        /// <summary>Try to read everything up to the given <paramref name="delimiter"/>.</summary>
        /// <param name="span">The read data, if any.</param>
        /// <param name="delimiter">The delimiter to look for.</param>
        /// <param name="advancePastDelimiter">True to move past the <paramref name="delimiter"/> if found.</param>
        /// <returns>True if the <paramref name="delimiter"/> was found.</returns>
        public bool TryReadTo(out ReadOnlySpan <byte> span, byte delimiter, bool advancePastDelimiter = true)
        {
            ReadOnlySpan <byte> remaining = UnreadSpan;

#if NET
            int index = remaining.IndexOf(delimiter);
#else
            int index = SpanHelpers.IndexOf(ref MemoryMarshal.GetReference(remaining), delimiter, remaining.Length);
#endif

            uint uIndex = (uint)index;
            if (SharedConstants.TooBigOrNegative >= uIndex) // index != -1
            {
                span = 0u >= uIndex ? default : remaining.Slice(0, index);
                       AdvanceCurrentSpan(index + (advancePastDelimiter ? 1 : 0));
                       return(true);
            }

            return(TryReadToSlow(out span, delimiter, advancePastDelimiter));
        }
Example #5
0
        public static void WriteMachineEndian <T>(Span <byte> buffer, ref T value)
            where T : struct
        {
#if netstandard
            if (SpanHelpers.IsReferenceOrContainsReferences <T>())
            {
                ThrowHelper.ThrowArgumentException_InvalidTypeWithPointersNotSupported(typeof(T));
            }
#else
            if (RuntimeHelpers.IsReferenceOrContainsReferences <T>())
            {
                ThrowHelper.ThrowArgumentException_InvalidTypeWithPointersNotSupported(typeof(T));
            }
#endif
            if ((uint)Unsafe.SizeOf <T>() > (uint)buffer.Length)
            {
                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length);
            }
            Unsafe.WriteUnaligned <T>(ref MemoryMarshal.GetReference(buffer), value);
        }
Example #6
0
        public int ForEachByte(int index, int count, IByteProcessor visitor)
        {
            var thisLength = this.length;

            if (0u >= (uint)thisLength)
            {
                return(IndexNotFound);
            }
            if (MathUtil.IsOutOfBounds(index, count, thisLength))
            {
                ThrowIndexOutOfRangeException_Index(index, count, thisLength);
            }
            var idx = SpanHelpers.ForEachByte(ref this.value[this.offset + index], visitor, count);

            if ((uint)count > (uint)idx)
            {
                return(index + idx);
            }
            return(IndexNotFound);
        }
Example #7
0
        public void TestNoMatch_Byte()
        {
            var rnd = new Random(42);

            for (int length = 0; length <= byte.MaxValue; length++)
            {
                byte[] a      = new byte[length];
                byte   target = (byte)rnd.Next(0, 256);
                for (int i = 0; i < length; i++)
                {
                    byte val = (byte)(i + 1);
                    a[i] = val == target ? (byte)(target + 1) : val;
                }
                Span <byte> span = new Span <byte>(a);

                //int idx = span.IndexOf(target);
                int idx = SpanHelpers.FindIndex(ref MemoryMarshal.GetReference(span), x => x == target, span.Length);
                Assert.Equal(-1, idx);
            }
        }
Example #8
0
        public static T ReadMachineEndian <T>(ReadOnlySpan <byte> buffer)
            where T : struct
        {
#if netstandard
            if (SpanHelpers.IsReferenceOrContainsReferences <T>())
            {
                ThrowHelper.ThrowArgumentException_InvalidTypeWithPointersNotSupported(typeof(T));
            }
#else
            if (RuntimeHelpers.IsReferenceOrContainsReferences <T>())
            {
                ThrowHelper.ThrowArgumentException_InvalidTypeWithPointersNotSupported(typeof(T));
            }
#endif
            if (Unsafe.SizeOf <T>() > buffer.Length)
            {
                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length);
            }
            return(Unsafe.ReadUnaligned <T>(ref buffer.DangerousGetPinnableReference()));
        }
Example #9
0
        public void TestMatch_Byte()
        {
            for (int length = 0; length <= byte.MaxValue; length++)
            {
                byte[] a = new byte[length];
                for (int i = 0; i < length; i++)
                {
                    a[i] = (byte)(i + 1);
                }
                Span <byte> span = new Span <byte>(a);

                for (int targetIndex = 0; targetIndex < length; targetIndex++)
                {
                    byte target = a[targetIndex];
                    //int idx = span.IndexOf(target);
                    int idx = SpanHelpers.FindIndex(ref MemoryMarshal.GetReference(span), x => x == target, span.Length);
                    Assert.Equal(targetIndex, idx);
                }
            }
        }
Example #10
0
        public void TestMultipleMatchLastIndexOf_Byte()
        {
            for (int length = 2; length <= byte.MaxValue; length++)
            {
                byte[] a = new byte[length];
                for (int i = 0; i < length; i++)
                {
                    byte val = (byte)(i + 1);
                    a[i] = val == 200 ? (byte)201 : val;
                }

                a[length - 1] = 200;
                a[length - 2] = 200;

                Span <byte> span = new Span <byte>(a);
                //int idx = span.LastIndexOf<byte>(200);
                int idx = SpanHelpers.FindLastIndex(ref MemoryMarshal.GetReference(span), x => x == 200, span.Length);
                Assert.Equal(length - 1, idx);
            }
        }
Example #11
0
        public static bool TryWriteMachineEndian <T>(Span <byte> buffer, ref T value)
            where T : struct
        {
#if netstandard
            if (SpanHelpers.IsReferenceOrContainsReferences <T>())
            {
                ThrowHelper.ThrowArgumentException_InvalidTypeWithPointersNotSupported(typeof(T));
            }
#else
            if (RuntimeHelpers.IsReferenceOrContainsReferences <T>())
            {
                ThrowHelper.ThrowArgumentException_InvalidTypeWithPointersNotSupported(typeof(T));
            }
#endif
            if (Unsafe.SizeOf <T>() > (uint)buffer.Length)
            {
                return(false);
            }
            Unsafe.WriteUnaligned <T>(ref buffer.DangerousGetPinnableReference(), value);
            return(true);
        }
Example #12
0
        private static string Print(this AesXtsFile xtsFile, int contentType)
        {
            int colLen = 36;
            var sb     = new StringBuilder();

            sb.AppendLine();

            sb.AppendLine("NAX0:");

            AesXtsFileHeader header = xtsFile.Header;
            uint             magic  = header.Magic;

            PrintItem(sb, colLen, "    Magic:", Util.GetUtf8String(SpanHelpers.AsReadOnlyByteSpan(ref magic)));
            PrintItem(sb, colLen, "    Content Type:", GetContentType(contentType));
            PrintItem(sb, colLen, "    Content Size:", $"{header.Size:x12}");
            PrintItem(sb, colLen, "    Header HMAC:", header.Signature);
            PrintItem(sb, colLen, "    Encrypted Keys:", header.EncryptedKey1.Concat(header.EncryptedKey2).ToArray());
            PrintItem(sb, colLen, "    Decrypted Keys:", header.DecryptedKey1.Concat(header.DecryptedKey2).ToArray());

            return(sb.ToString());
        }
Example #13
0
        public static bool TryWriteMachineEndian <T>(Span <byte> destination, ref T value)
            where T : struct
        {
#if netstandard
            if (SpanHelpers.IsReferenceOrContainsReferences <T>())
            {
                ThrowHelper.ThrowArgumentException_InvalidTypeWithPointersNotSupported(typeof(T));
            }
#else
            if (RuntimeHelpers.IsReferenceOrContainsReferences <T>())
            {
                ThrowHelper.ThrowArgumentException_InvalidTypeWithPointersNotSupported(typeof(T));
            }
#endif
            if (Unsafe.SizeOf <T>() > (uint)destination.Length)
            {
                return(false);
            }
            Unsafe.WriteUnaligned <T>(ref MemoryMarshal.GetReference(destination), value);
            return(true);
        }
        private bool TryReadToInternal(out ReadOnlySequence <byte> sequence, byte delimiter, bool advancePastDelimiter, int skip = 0)
        {
            Debug.Assert(skip >= 0);
            ByteBufferReader copy = this;

            if (skip > 0)
            {
                Advance(skip);
            }
            ReadOnlySpan <byte> remaining = UnreadSpan;

            while (_moreData)
            {
                int  index  = SpanHelpers.IndexOf(ref MemoryMarshal.GetReference(remaining), delimiter, remaining.Length);
                uint uIndex = (uint)index;
                if (SharedConstants.TooBigOrNegative >= uIndex) // index != -1
                {
                    // Found the delimiter. Move to it, slice, then move past it.
                    if (uIndex > 0u) // 此时 index 为非负值
                    {
                        AdvanceCurrentSpan(index);
                    }

                    sequence = _sequence.Slice(copy.Position, Position);
                    if (advancePastDelimiter)
                    {
                        Advance(1);
                    }
                    return(true);
                }

                AdvanceCurrentSpan(remaining.Length);
                remaining = _currentSpan;
            }

            // Didn't find anything, reset our original state.
            this     = copy;
            sequence = default;
            return(false);
        }
Example #15
0
        private void AddUpdate(string path)
        {
            if (File.Exists(path))
            {
                using (FileStream file = new FileStream(path, FileMode.Open, FileAccess.Read))
                {
                    PartitionFileSystem nsp = new PartitionFileSystem(file.AsStorage());

                    try
                    {
                        (Nca patchNca, Nca controlNca) = ApplicationLoader.GetGameUpdateDataFromPartition(_virtualFileSystem, nsp, _titleId, 0);

                        if (controlNca != null && patchNca != null)
                        {
                            ApplicationControlProperty controlData = new ApplicationControlProperty();

                            controlNca.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.None).OpenFile(out IFile nacpFile, "/control.nacp".ToU8Span(), OpenMode.Read).ThrowIfFailure();
                            nacpFile.Read(out _, 0, SpanHelpers.AsByteSpan(ref controlData), ReadOption.None).ThrowIfFailure();

                            RadioButton radioButton = new RadioButton($"Version {controlData.DisplayVersion.ToString()} - {path}");
                            radioButton.JoinGroup(_noUpdateRadioButton);

                            _availableUpdatesBox.Add(radioButton);
                            _radioButtonToPathDictionary.Add(radioButton, path);

                            radioButton.Show();
                            radioButton.Active = true;
                        }
                        else
                        {
                            GtkDialog.CreateErrorDialog("The specified file does not contain an update for the selected title!");
                        }
                    }
                    catch (Exception exception)
                    {
                        GtkDialog.CreateErrorDialog($"{exception.Message}. Errored File: {path}");
                    }
                }
            }
        }
Example #16
0
        public static bool TryReadMachineEndian <T>(ReadOnlySpan <byte> source, out T value)
            where T : struct
        {
#if netstandard
            if (SpanHelpers.IsReferenceOrContainsReferences <T>())
            {
                ThrowHelper.ThrowArgumentException_InvalidTypeWithPointersNotSupported(typeof(T));
            }
#else
            if (RuntimeHelpers.IsReferenceOrContainsReferences <T>())
            {
                ThrowHelper.ThrowArgumentException_InvalidTypeWithPointersNotSupported(typeof(T));
            }
#endif
            if (Unsafe.SizeOf <T>() > (uint)source.Length)
            {
                value = default;
                return(false);
            }
            value = Unsafe.ReadUnaligned <T>(ref MemoryMarshal.GetReference(source));
            return(true);
        }
Example #17
0
        public bool ContentEquals(ICharSequence other)
        {
            if (ReferenceEquals(this, other))
            {
                return(true);
            }

            var thisLength = this.length;

            if (other is null || thisLength != other.Count)
            {
                return(false);
            }

            switch (other)
            {
            case AsciiString asciiStr:
                return(this.GetHashCode() == asciiStr.GetHashCode()
#if NET
                       && this.AsciiSpan.SequenceEqual(asciiStr.AsciiSpan));
#else
                       && SpanHelpers.SequenceEqual(ref MemoryMarshal.GetReference(this.AsciiSpan), ref MemoryMarshal.GetReference(asciiStr.AsciiSpan), thisLength);
Example #18
0
        public int LastIndexOf(ICharSequence subString, int start)
        {
            int  thisLen  = this.length;
            uint uThisLen = (uint)thisLen;

            if (0u >= uThisLen)
            {
                return(IndexNotFound);
            }

            int subCount = subString.Count;

            start = Math.Min(start, thisLen - subCount);
            uint uStart = (uint)start;

            if (uStart > SharedConstants.TooBigOrNegative)
            {
                return(IndexNotFound);
            }
            if (0u >= (uint)subCount)
            {
                return(start);
            }

            if (subString is IHasAsciiSpan hasAscii)
            {
                return(SpanHelpers.LastIndexOf(
                           ref MemoryMarshal.GetReference(this.AsciiSpan), start + subCount,
                           ref MemoryMarshal.GetReference(hasAscii.AsciiSpan), subCount));
            }
            if (subString is IHasUtf16Span hasUtf16)
            {
                return(SpanHelpers.LastIndexOf(
                           ref MemoryMarshal.GetReference(this.Utf16Span), start + subCount,
                           ref MemoryMarshal.GetReference(hasUtf16.Utf16Span), subCount));
            }

            return(LastIndexOf0(subString, start));
        }
Example #19
0
        public static bool TryReadMachineEndian <T>(ReadOnlySpan <byte> buffer, out T value)
            where T : struct
        {
#if netstandard
            if (SpanHelpers.IsReferenceOrContainsReferences <T>())
            {
                ThrowHelper.ThrowArgumentException_InvalidTypeWithPointersNotSupported(typeof(T));
            }
#else
            if (RuntimeHelpers.IsReferenceOrContainsReferences <T>())
            {
                throw new ArgumentException(SR.Format(SR.Argument_InvalidTypeWithPointersNotSupported, typeof(T)));
            }
#endif
            if (Unsafe.SizeOf <T>() > (uint)buffer.Length)
            {
                value = default;
                return(false);
            }
            value = Unsafe.ReadUnaligned <T>(ref buffer.DangerousGetPinnableReference());
            return(true);
        }
Example #20
0
        public Result ReadKeyValue(Span <byte> keyBuffer, Span <byte> valueBuffer)
        {
            // This should only be called after ReadEntryCount.
            Assert.SdkNotEqual(_offset, 0);

            // Read the next entry header.
            Unsafe.SkipInit(out KeyValueArchiveEntryHeader header);

            Result rc = Read(SpanHelpers.AsByteSpan(ref header));

            if (rc.IsFailure())
            {
                return(rc);
            }

            if (!header.IsValid())
            {
                return(ResultKvdb.InvalidKeyValue.Log());
            }

            // Key size and Value size must be correct.
            Assert.SdkEqual(keyBuffer.Length, header.KeySize);
            Assert.SdkEqual(valueBuffer.Length, header.ValueSize);

            rc = Read(keyBuffer);
            if (rc.IsFailure())
            {
                return(rc);
            }

            rc = Read(valueBuffer);
            if (rc.IsFailure())
            {
                return(rc);
            }

            return(Result.Success);
        }
        public Result GetEntryCount(out long entryCount)
        {
            entryCount = 0;
            long count = 0;

            Result rc = BaseFileSystem.OpenDirectory(out IDirectory _, Path,
                                                     OpenDirectoryMode.All | OpenDirectoryMode.NoFileSize);

            if (rc.IsFailure())
            {
                return(rc);
            }

            var entry = new DirectoryEntry();
            Span <DirectoryEntry> entrySpan = SpanHelpers.AsSpan(ref entry);

            while (true)
            {
                rc = ParentDirectory.Read(out long baseEntriesRead, entrySpan);
                if (rc.IsFailure())
                {
                    return(rc);
                }

                if (baseEntriesRead == 0)
                {
                    break;
                }

                if (CanReturnEntry(entry, IsConcatenationFile(entry)))
                {
                    count++;
                }
            }

            entryCount = count;
            return(Result.Success);
        }
        public static bool Contains(this ICharSequence sequence, char c)
        {
            switch (sequence)
            {
            case null:
                return(false);

            case IHasAsciiSpan hasAscii:
                if ((uint)c > AsciiString.uMaxCharValue)
                {
                    return(false);
                }
#if NET
                return(hasAscii.AsciiSpan.Contains((byte)c));
#else
                var asciiSpan = hasAscii.AsciiSpan;
                return(SpanHelpers.Contains(ref MemoryMarshal.GetReference(asciiSpan), (byte)c, asciiSpan.Length));
#endif

            case IHasUtf16Span hasUtf16:
#if NET
#else
                var utf16Span = hasUtf16.Utf16Span;
                return(SpanHelpers.Contains(ref MemoryMarshal.GetReference(utf16Span), c, utf16Span.Length));
#endif

            default:
                int length = sequence.Count;
                for (int i = 0; i < length; i++)
                {
                    if (sequence[i] == c)
                    {
                        return(true);
                    }
                }
                return(false);
            }
        }
        public override bool Equals(object obj)
        {
            if (ReferenceEquals(this, obj))
            {
                return(true);
            }

            switch (obj)
            {
            case AppendableCharSequence other:
                return(_pos == other._pos &&
                       SpanHelpers.SequenceEqual(ref MemoryMarshal.GetReference(AsciiSpan), ref MemoryMarshal.GetReference(other.AsciiSpan), _pos));

            case IHasAsciiSpan hasAscii:
                return(AsciiSpan.SequenceEqual(hasAscii.AsciiSpan));

            case ICharSequence seq:
                return(ContentEquals(seq));

            default:
                return(false);
            }
        }
        bool IEquatable <ICharSequence> .Equals(ICharSequence other)
        {
            if (ReferenceEquals(this, other))
            {
                return(true);
            }

            switch (other)
            {
            case null:
                return(false);

            case AppendableCharSequence comparand:
                return(_pos == comparand._pos &&
                       SpanHelpers.SequenceEqual(ref MemoryMarshal.GetReference(AsciiSpan), ref MemoryMarshal.GetReference(comparand.AsciiSpan), _pos));

            case IHasAsciiSpan hasAscii:
                return(AsciiSpan.SequenceEqual(hasAscii.AsciiSpan));

            default:
                return(false);
            }
        }
Example #25
0
        /// <summary>
        ///     Returns <c>true</c> if and only if the two specified buffers are
        ///     identical to each other for {@code length} bytes starting at {@code aStartIndex}
        ///     index for the {@code a} buffer and {@code bStartIndex} index for the {@code b} buffer.
        ///     A more compact way to express this is:
        ///     <p />
        ///     {@code a[aStartIndex : aStartIndex + length] == b[bStartIndex : bStartIndex + length]}
        /// </summary>
        public static bool Equals(IByteBuffer a, int aStartIndex, IByteBuffer b, int bStartIndex, int length)
        {
            if (aStartIndex < 0 || bStartIndex < 0 || length < 0)
            {
                ThrowHelper.ThrowArgumentException_NonNegative();
            }
            if (a.WriterIndex - length < aStartIndex || b.WriterIndex - length < bStartIndex)
            {
                return(false);
            }

            if (a.IsSingleIoBuffer && b.IsSingleIoBuffer)
            {
                var spanA = a.GetReadableSpan(aStartIndex, length);
                var spanB = b.GetReadableSpan(bStartIndex, length);
#if NET
                return(spanA.SequenceEqual(spanB));
#else
                return(SpanHelpers.SequenceEqual(ref MemoryMarshal.GetReference(spanA), ref MemoryMarshal.GetReference(spanB), length));
#endif
            }
            return(EqualsSlow(a, aStartIndex, b, bStartIndex, length));
        }
Example #26
0
            protected override Result DoGetEntryCount(out long entryCount)
            {
                entryCount = 0;
                long totalEntryCount = 0;
                var  entry           = new DirectoryEntry();

                // todo: Efficient way to remove duplicates
                var names = new HashSet <string>();

                // Open new directories for each source because we need to remove duplicate entries
                foreach (IFileSystem fs in SourceFileSystems)
                {
                    Result rc = fs.OpenDirectory(out IDirectory dir, Path, Mode);
                    if (rc.IsFailure())
                    {
                        return(rc);
                    }

                    long entriesRead;
                    do
                    {
                        rc = dir.Read(out entriesRead, SpanHelpers.AsSpan(ref entry));
                        if (rc.IsFailure())
                        {
                            return(rc);
                        }

                        if (entriesRead == 1 && names.Add(StringUtils.Utf8ZToString(entry.Name)))
                        {
                            totalEntryCount++;
                        }
                    } while (entriesRead != 0);
                }

                entryCount = totalEntryCount;
                return(Result.Success);
            }
Example #27
0
        public IStorage OpenRawStorageWithPatch(Nca patchNca, int index)
        {
            IStorage patchStorage = patchNca.OpenRawStorage(index);
            IStorage baseStorage  = SectionExists(index) ? OpenRawStorage(index) : new NullStorage();

            patchStorage.GetSize(out long patchSize).ThrowIfFailure();
            baseStorage.GetSize(out long baseSize).ThrowIfFailure();

            NcaFsHeader    header    = patchNca.Header.GetFsHeader(index);
            NcaFsPatchInfo patchInfo = header.GetPatchInfo();

            if (patchInfo.RelocationTreeSize == 0)
            {
                return(patchStorage);
            }

            var treeHeader = new BucketTree.Header();

            patchInfo.RelocationTreeHeader.CopyTo(SpanHelpers.AsByteSpan(ref treeHeader));
            long nodeStorageSize  = IndirectStorage.QueryNodeStorageSize(treeHeader.EntryCount);
            long entryStorageSize = IndirectStorage.QueryEntryStorageSize(treeHeader.EntryCount);

            var relocationTableStorage = new SubStorage(patchStorage, patchInfo.RelocationTreeOffset, patchInfo.RelocationTreeSize);
            var cachedTableStorage     = new CachedStorage(relocationTableStorage, IndirectStorage.NodeSize, 4, true);

            var tableNodeStorage  = new SubStorage(cachedTableStorage, 0, nodeStorageSize);
            var tableEntryStorage = new SubStorage(cachedTableStorage, nodeStorageSize, entryStorageSize);

            var storage = new IndirectStorage();

            storage.Initialize(tableNodeStorage, tableEntryStorage, treeHeader.EntryCount).ThrowIfFailure();

            storage.SetStorage(0, baseStorage, 0, baseSize);
            storage.SetStorage(1, patchStorage, 0, patchSize);

            return(storage);
        }
Example #28
0
        public Result Read(out long readCount, Span <byte> saveDataInfoBuffer)
        {
            readCount = default;

            Span <SaveDataInfo> outInfo = MemoryMarshal.Cast <byte, SaveDataInfo>(saveDataInfoBuffer);

            SaveDataInfo tempInfo      = default;
            Span <byte>  tempInfoBytes = SpanHelpers.AsByteSpan(ref tempInfo);

            ISaveDataInfoReader reader = Reader.Target;
            int count = 0;

            while (count < outInfo.Length)
            {
                Result rc = reader.Read(out long baseReadCount, tempInfoBytes);
                if (rc.IsFailure())
                {
                    return(rc);
                }

                if (baseReadCount == 0)
                {
                    break;
                }

                if (Filter.Matches(ref tempInfo))
                {
                    outInfo[count] = tempInfo;

                    count++;
                }
            }

            readCount = count;

            return(Result.Success);
        }
            /// <summary>
            /// Adds a new entry to the bucket tree.
            /// </summary>
            /// <typeparam name="T">The type of the entry to add. Added entries should all be the same type.</typeparam>
            /// <param name="entry">The entry to add.</param>
            /// <returns>The <see cref="Result"/> of the operation.</returns>
            public Result Add <T>(ref T entry) where T : unmanaged
            {
                Assert.True(Unsafe.SizeOf <T>() == EntrySize);

                if (CurrentEntryIndex >= EntryCount)
                {
                    return(ResultFs.OutOfRange.Log());
                }

                // The entry offset must always be the first 8 bytes of the struct
                long entryOffset = BinaryPrimitives.ReadInt64LittleEndian(SpanHelpers.AsByteSpan(ref entry));

                if (entryOffset <= CurrentOffset)
                {
                    return(ResultFs.InvalidOffset.Log());
                }

                Result rc = FinalizePreviousEntrySet(entryOffset);

                if (rc.IsFailure())
                {
                    return(rc);
                }

                AddEntryOffset(entryOffset);

                // Write the new entry
                int indexInEntrySet = CurrentEntryIndex % EntriesPerEntrySet;

                _entrySet.GetNode <T>().GetWritableArray()[indexInEntrySet] = entry;

                CurrentOffset = entryOffset;
                CurrentEntryIndex++;

                return(Result.Success);
            }
Example #30
0
        private IStorage OpenAesCtrExStorage(IStorage baseStorage, int index)
        {
            NcaFsHeader    fsHeader = Header.GetFsHeader(index);
            NcaFsPatchInfo info     = fsHeader.GetPatchInfo();

            long sectionOffset = Header.GetSectionStartOffset(index);
            long sectionSize   = Header.GetSectionSize(index);

            long bktrOffset = info.RelocationTreeOffset;
            long bktrSize   = sectionSize - bktrOffset;
            long dataSize   = info.RelocationTreeOffset;

            byte[] key       = GetContentKey(NcaKeyType.AesCtr);
            byte[] counter   = Aes128CtrStorage.CreateCounter(fsHeader.Counter, bktrOffset + sectionOffset);
            byte[] counterEx = Aes128CtrStorage.CreateCounter(fsHeader.Counter, sectionOffset);

            IStorage bucketTreeData           = new CachedStorage(new Aes128CtrStorage(baseStorage.Slice(bktrOffset, bktrSize), key, counter, true), 4, true);
            var      encryptionBucketTreeData = new SubStorage(bucketTreeData,
                                                               info.EncryptionTreeOffset - bktrOffset, sectionSize - info.EncryptionTreeOffset);

            var cachedBucketTreeData = new CachedStorage(encryptionBucketTreeData, IndirectStorage.NodeSize, 6, true);

            var treeHeader = new BucketTree.Header();

            info.EncryptionTreeHeader.CopyTo(SpanHelpers.AsByteSpan(ref treeHeader));
            long nodeStorageSize  = IndirectStorage.QueryNodeStorageSize(treeHeader.EntryCount);
            long entryStorageSize = IndirectStorage.QueryEntryStorageSize(treeHeader.EntryCount);

            var tableNodeStorage  = new SubStorage(cachedBucketTreeData, 0, nodeStorageSize);
            var tableEntryStorage = new SubStorage(cachedBucketTreeData, nodeStorageSize, entryStorageSize);

            IStorage decStorage = new Aes128CtrExStorage(baseStorage.Slice(0, dataSize), tableNodeStorage,
                                                         tableEntryStorage, treeHeader.EntryCount, key, counterEx, true);

            return(new ConcatenationStorage(new[] { decStorage, bucketTreeData }, true));
        }