diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 0000000..e69de29 diff --git a/404.html b/404.html new file mode 100644 index 0000000..647e587 --- /dev/null +++ b/404.html @@ -0,0 +1,829 @@ + + + + + + + + + + + + + + + + + + Reloaded Memory Library + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ +

404 - Not found

+ +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/About-Memory/index.html b/About-Memory/index.html new file mode 100644 index 0000000..e51b60e --- /dev/null +++ b/About-Memory/index.html @@ -0,0 +1,1150 @@ + + + + + + + + + + + + + + + + + + + + + + + + Memory - Reloaded Memory Library + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Memory API

+
+

Info

+

Reloaded.Memory provides various abstractions that can be used to wrap around contiguous regions of memory.

+
+
+

All APIs listed here are zero overhead.

+
+
+

Stuff listed here isn't that impressive, but it's the basic building block for what follows next.

+
+

Memory & ExternalMemory

+
+

Info

+

The Memory and ExternalMemory classes are the most basic abstractions provided by Reloaded.Memory.
+They allow you to access memory either within the current or a target process.

+
+
+
+
+
while (ptr < maxAddress)
+{
+    result += *ptr;
+    ptr += 1;
+}
+
+
+
+
if (Polyfills.IsWindows())
+    return Kernel32.ReadProcessMemory(_processHandle, location, (nuint)buffer, numBytes, out _);
+
+if (Polyfills.IsLinux())
+    return Posix.process_vm_readv_k32(_processHandle, location, (nuint)buffer, numBytes);
+
+// And other cases!
+
+
+
+
// memory = Memory.Instance;
+while (ptr < maxAddress)
+{
+    result += memory.Read<nuint>((UIntPtr)ptr);
+    ptr += 1;
+}
+
+
+
+
// memory = new ExternalMemory(process);
+while (ptr < maxAddress)
+{
+    result += memory.Read<nuint>((UIntPtr)ptr);
+    ptr += 1;
+}
+
+
+
+
+

As you can see, with the library and its ICanReadWriteMemory interface; usage is unified across all sources. Instead +of having to write different code for different sources (first 2 examples), you can now write the same code for all sources.

+

And of course, various different utility methods are provided to make your life easier.

+
+
+
+
while (ptr < maxAddress)
+    Marshal.StructureToPtr(items[x++], (nint)offset, false);
+
+
+
+
byte* bufferPtr = new byte[structSize];
+bool succeeded = ReadProcessMemory(offset, bufferPtr, (nuint)structSize);
+if (!succeeded)
+    ThrowHelpers.ThrowReadExternalMemoryExceptionWindows(offset, structSize);
+
+Marshal.PtrToStructure((nint)bufferPtr, value);
+
+
+
+
while (ptr < maxAddress)
+    memory.WriteWithMarshalling(ptr, items[x++]);
+
+
+
+
while (ptr < maxAddress)
+    memory.WriteWithMarshalling(ptr, items[x++]);
+
+
+
+
+

All silly boilerplate needed to manipulate different sources is gone; and this is all done with zero-overhead.

+

Unified Memory Allocation API

+
+

Info

+

Structs like Memory and ExternalMemory employ ICanAllocateMemory API to make memory allocations convenient.

+
+
+
+
+
var allocation = NativeMemory.Alloc(100);
+
+
+
+
var allocation = Marshal.AllocHGlobal(100);
+
+
+
+
var allocation = memory.Allocate(100);
+
+
+
+
var allocation = memory.Allocate(100);
+
+
+
+
+

Now you can allocate in another process in a consistent manner. Useful?

+
+

ICanAllocateMemory for ExternalMemory currently implemented in Windows only; PRs for Linux and OSX.

+
+

Unified Permission Change API

+
+

Info

+

Structs like Memory and ExternalMemory employ ICanChangeMemoryProtection API to allow you to change memory permissions.

+

This allows you to make existing code etc. in memory writable for editing.

+
+
+
+
+
if (Polyfills.IsWindows())
+{
+    bool result = Kernel32.VirtualProtect(memoryAddress, (nuint)size, (Kernel32.MEM_PROTECTION)newProtection,
+        out Kernel32.MEM_PROTECTION oldPermissions);
+    if (!result)
+        ThrowHelpers.ThrowMemoryPermissionExceptionWindows(memoryAddress, size, newProtection);
+
+    return (nuint)oldPermissions;
+}
+
+if (Polyfills.IsLinux() || Polyfills.IsMacOS())
+{
+    // ... lot more boilerplate
+}
+
+
+
+
var oldPermissions = source.ChangeProtection(address, length, MemoryProtection.READ);
+
+
+
+
var oldPermissions = source.ChangeProtection(address, length, MemoryProtection.READ);
+
+
+
+
+

Pretty useful huh?

+
+

ICanChangeMemoryProtection for ExternalMemory currently implemented in Windows only; PRs for Linux and OSX are welcome.

+
+

Extensions

+
+

Info

+

These interfaces, and combinations of them allow for some very useful utility methods to be made.

+
+

Temporary allocate a buffer:

+
// Automatically disposed, even on exception
+using var alloc = memory.AllocateDisposable(DataSize);
+
+

Temporary change memory permission:

+
using var alloc = memory.ChangeProtectionDisposable(DataSize);
+
+

Temporary change memory permission, write data, and restore:

+
memory.SafeWrite(Alloc.Address, Data.AsSpanFast());
+
+

Reference Benchmarks

+
+

In most cases, the abstractions generate 1:1 code that matches exactly the same performance as working with raw pointers.

+
+
|                        Method |     Mean |   Error |  StdDev | Code Size | Allocated |
+|------------------------------ |---------:|--------:|--------:|----------:|----------:|
+|                ReadViaPointer | 130.7 ns | 0.77 ns | 0.69 ns |      49 B |         - |
+|                 ReadViaMemory | 132.4 ns | 0.71 ns | 0.66 ns |      52 B |         - |
+| ReadViaMemory_ViaOutParameter | 132.2 ns | 1.81 ns | 1.70 ns |      52 B |         - |
+|               WriteViaPointer | 117.4 ns | 1.55 ns | 1.45 ns |      48 B |         - |
+|                WriteViaMemory | 117.8 ns | 1.67 ns | 1.57 ns |      48 B |         - |
+
+

ReadViaPointer and WriteViaPointer are using raw pointers; remaining tests are using the abstractions.

+ + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/Extensions/ArrayExtensions/index.html b/Extensions/ArrayExtensions/index.html new file mode 100644 index 0000000..dd2335e --- /dev/null +++ b/Extensions/ArrayExtensions/index.html @@ -0,0 +1,1145 @@ + + + + + + + + + + + + + + + + + + + + + + + + Array - Reloaded Memory Library + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + + + + + +
+
+ + + + + + + + +

ArrayExtensions

+
+

Partially forked from Community Toolkit.

+
+
+

Utility class providing high performance extension methods for working with arrays.

+
+

ArrayExtensions is a utility class that provides extension methods for arrays, including methods for getting references +without bounds checks, counting occurrences of a value, checking covariance, and converting arrays to spans.

+

Methods

+

DangerousGetReference

+
public static ref T DangerousGetReference<T>(this T[] array)
+
+

Returns a reference to the first element within a given T[] array, with no bounds checks. The caller is responsible +for performing checks in case the returned value is dereferenced.

+

DangerousGetReferenceAt

+
public static ref T DangerousGetReferenceAt<T>(this T[] array, int i)
+
+

Returns a reference to an element at a specified index within a given T[] array, with no bounds checks. +The caller is responsible for ensuring the i parameter is valid.

+

Count

+
public static int Count<T>(this T[] array, T value) where T : IEquatable<T>
+
+

Counts the number of occurrences of a given value in a target T[] array instance.

+

IsCovariant

+
public static bool IsCovariant<T>(this T[] array)
+
+

Checks whether or not a given T[] array is covariant.

+

AsSpanFast

+
+

Only supported on .NET 5 and above. Older runtimes will use default AsSpan.

+
+
public static Span<T> AsSpanFast<T>(this T[] data)
+
+

Converts a byte array to a Span without doing a null check.

+

Usage

+

Get Reference without Bounds Checks

+
int[] array = new int[] { 1, 2, 3 };
+ref int firstElement = ref array.DangerousGetReference();
+
+

Get Reference at Specific Index without Bounds Checks

+
int[] array = new int[] { 1, 2, 3 };
+ref int elementAtTwo = ref array.DangerousGetReferenceAt(2);
+
+

Count Occurrences of a Value

+
int[] array = new int[] { 1, 2, 2, 3, 2 };
+int count = array.Count(2);
+
+

Check Covariance

+
object[] array = new object[] { "a", "b", "c" };
+bool isCovariant = array.IsCovariant<string>();
+
+

Convert Array to Span without Null Check

+
int[] array = new int[] { 1, 2, 3 };
+Span<int> span = array.AsSpanFast();
+
+ + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/Extensions/BoolExtensions/index.html b/Extensions/BoolExtensions/index.html new file mode 100644 index 0000000..83a9569 --- /dev/null +++ b/Extensions/BoolExtensions/index.html @@ -0,0 +1,1071 @@ + + + + + + + + + + + + + + + + + + + + + + + + Bool - Reloaded Memory Library + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

BoolExtensions

+
+

Forked from Community Toolkit.

+
+
+

Utility class providing high performance extension methods for working with the bool type.

+
+

BoolExtensions is a utility class that provides extension methods for the bool type, including converting bool values +to byte, int, and long masks.

+

Methods

+

ToByte

+
public static unsafe byte ToByte(this bool flag)
+
+

Converts the given bool value into a byte. Returns 1 if flag is true, 0 otherwise. +This method does not contain branching instructions.

+

ToBitwiseMask32

+
public static unsafe int ToBitwiseMask32(this bool flag)
+
+

Converts the given bool value to an int mask with all bits representing the value of the input flag +(either 0xFFFFFFFF or 0x00000000). This method does not contain branching instructions.

+

ToBitwiseMask64

+
public static unsafe long ToBitwiseMask64(this bool flag)
+
+

Converts the given bool value to a long mask with all bits representing the value of the input flag +(either all 1s or 0s). This method does not contain branching instructions.

+

Usage

+

Convert Bool to Byte

+
bool flag = true;
+byte result = flag.ToByte();
+
+

Convert Bool to Int Mask

+
bool flag = true;
+int mask = flag.ToBitwiseMask32();
+
+

Convert Bool to Long Mask

+
bool flag = true;
+long mask = flag.ToBitwiseMask64();
+
+ + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/Extensions/EndianExtensions/index.html b/Extensions/EndianExtensions/index.html new file mode 100644 index 0000000..eb37a06 --- /dev/null +++ b/Extensions/EndianExtensions/index.html @@ -0,0 +1,1166 @@ + + + + + + + + + + + + + + + + + + + + + + + + Endian - Reloaded Memory Library + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + + + + + +
+
+ + + + + + + + +

EndianExtensions

+
+

Provides extension methods for converting between endianness.

+
+

EndianExtensions is a static class that offers methods to convert primitive data types and any structure implementing the ICanReverseEndian interface to big or little endian format.

+

The conversions check the system's endianness and only perform byte-swapping if necessary, making the operation efficient by avoiding redundant processing on systems with matching endianness.

+
+

The JIT will eliminate no-operations here, so e.g. calling AsLittleEndian on a Little Endian machine has 0 overhead.

+
+

Methods

+

AsLittleEndian (Overloads for various types)

+
public static byte AsLittleEndian(this byte value)
+public static sbyte AsLittleEndian(this sbyte value)
+public static short AsLittleEndian(this short value)
+public static ushort AsLittleEndian(this ushort value)
+public static int AsLittleEndian(this int value)
+public static uint AsLittleEndian(this uint value)
+public static long AsLittleEndian(this long value)
+public static ulong AsLittleEndian(this ulong value)
+public static float AsLittleEndian(this float value)
+public static double AsLittleEndian(this double value)
+public static T AsLittleEndian<T>(this T value) where T : struct, ICanReverseEndian
+
+

Converts the given value to little endian format. If the system is already little endian, no conversion is performed.

+

Parameters

+
    +
  • value: The value to convert to little endian.
  • +
+

Returns

+

The value in little endian format.

+
+

AsBigEndian (Overloads for various types)

+
public static byte AsBigEndian(this byte value)
+public static sbyte AsBigEndian(this sbyte value)
+public static short AsBigEndian(this short value)
+public static ushort AsBigEndian(this ushort value)
+public static int AsBigEndian(this int value)
+public static uint AsBigEndian(this uint value)
+public static long AsBigEndian(this long value)
+public static ulong AsBigEndian(this ulong value)
+public static float AsBigEndian(this float value)
+public static double AsBigEndian(this double value)
+public static T AsBigEndian<T>(this T value) where T : struct, ICanReverseEndian
+
+

Converts the given value to big endian format. If the system is already big endian, no conversion is performed.

+

Parameters

+
    +
  • value: The value to convert to big endian.
  • +
+

Returns

+

The value in big endian format.

+

Usage

+

Convert an Integer to Little Endian Format

+
int myValue = 12345678;
+int littleEndianValue = myValue.AsLittleEndian();
+
+

Convert a Double to Big Endian Format

+
double myValue = 123.456;
+double bigEndianValue = myValue.AsBigEndian();
+
+

Convert a Custom Structure to Big Endian Format

+
+

For structs which implement ICanReverseEndian

+
+
var myStruct = new MyStruct { /* ... */ };
+var asBig = myStruct.AsBigEndian();
+
+ + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/Extensions/EnumExtensions/index.html b/Extensions/EnumExtensions/index.html new file mode 100644 index 0000000..e7d136f --- /dev/null +++ b/Extensions/EnumExtensions/index.html @@ -0,0 +1,1086 @@ + + + + + + + + + + + + + + + + + + + + + + + + Enum - Reloaded Memory Library + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

EnumExtensions

+
+

Provides high-performance extension methods for working with enums.

+
+

EnumExtensions is a utility class that , including checking for the presence of a specified flag in an enum value using unsafe code for faster execution.

+

Methods

+

HasFlagFast

+
public static bool HasFlagFast<T>(this T value, T flag) where T : unmanaged, Enum
+
+

Determines if the given enum has a specified flag. This method uses unsafe code for faster execution and skips type check.

+

Parameters

+
    +
  • value: The value to check.
  • +
  • flag: The flag to check.
  • +
+

Returns

+

true if the enum is contained in the value, false otherwise.

+

Type Parameters

+
    +
  • T: The type to check the flag of.
  • +
+

Exceptions

+
    +
  • NotSupportedException: This type of enum is not supported.
  • +
+

Usage

+

Check if an Enum Value Contains a Specific Flag

+
[Flags]
+enum MyEnum : int
+{
+    None = 0,
+    Flag1 = 1,
+    Flag2 = 2,
+    Flag3 = 4,
+}
+
+MyEnum value = MyEnum.Flag1 | MyEnum.Flag3;
+bool hasFlag1 = value.HasFlagFast(MyEnum.Flag1); // True
+bool hasFlag2 = value.HasFlagFast(MyEnum.Flag2); // False
+bool hasFlag3 = value.HasFlagFast(MyEnum.Flag3); // True
+
+ + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/Extensions/SpanExtensions/index.html b/Extensions/SpanExtensions/index.html new file mode 100644 index 0000000..71e1f7b --- /dev/null +++ b/Extensions/SpanExtensions/index.html @@ -0,0 +1,1343 @@ + + + + + + + + + + + + + + + + + + + + + + + + Span - Reloaded Memory Library + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + + + + + +
+
+ + + + + + + + +

SpanExtensions

+
+

Partially forked from Community Toolkit.

+
+
+

Utility class providing high performance extension methods for working with spans.

+
+

SpanExtensions is a utility class that provides extension methods for spans, including methods for casting, slicing, +replacing elements, and finding offsets.

+

Methods

+

CastFast

+
+

Not accelerated on .NET Framework and Standard 2.0

+
+

public static Span<TTo> CastFast<TFrom, TTo>(this Span<TFrom> data) where TFrom : struct where TTo : struct
+
+Casts a Span<TFrom> to a Span<TTo> without copying the underlying data.

+

DangerousGetReference

+

public static ref T DangerousGetReference<T>(this Span<T> span)
+
+Returns a reference to the first element within a given Span<T>, with no bounds checks.

+

DangerousGetReferenceAt

+

public static ref T DangerousGetReferenceAt<T>(this Span<T> span, int i)
+
+Returns a reference to an element at a specified index within a given Span<T>, with no bounds checks.
+The caller is responsible for ensuring the i parameter is valid.

+

AsBytes

+

public static Span<byte> AsBytes<T>(this Span<T> span) where T : unmanaged
+
+Converts a Span<T> to a Span<byte> without copying the underlying data.

+

Cast

+

public static Span<TTo> Cast<TFrom, TTo>(this Span<TFrom> span) where TFrom : unmanaged where TTo : unmanaged
+
+Casts a Span<TFrom> to a Span<TTo> without copying the underlying data, when both types are unmanaged.

+

IndexOf

+
public static unsafe int IndexOf<T>(this Span<T> span, ref T value)
+
+

Gets the index of an element within given Span<T> based on a reference to an element inside the Span<T>.

+

Count

+

public static int Count<T>(this Span<T> span, T value) where T : IEquatable<T>
+
+Counts the number of occurrences of a given value in a target Span<T> instance.

+

SliceFast

+
+

Not accelerated on .NET Framework and Standard 2.0

+
+

public static Span<T> SliceFast<T>(this Span<T> data, int start, int length)
+public static ReadOnlySpan<T> SliceFast<T>(this ReadOnlySpan<T> data, int start, int length)
+public static ReadOnlySpan<T> SliceFast<T>(this ReadOnlySpan<T> data, Range range)
+public static Span<T> SliceFast<T>(this Span<T> data, Range range)
+public static Span<T> SliceFast<T>(this Span<T> data, int start)
+public static ReadOnlySpan<T> SliceFast<T>(this ReadOnlySpan<T> data, int start)
+
+Performs a slice operation on a Span<T> or ReadOnlySpan<T> without performing bounds checks. +This supports ranges, so span.SliceFast(1..3) is valid.

+

Replace

+

public static Span<char> Replace(this Span<char> data, char oldValue, char newValue, Span<char> buffer)
+public static unsafe Span<T> Replace<T>(this Span<T> data, T oldValue, T newValue, Span<T> buffer) where T : unmanaged, IEquatable<T>
+
+Replaces all occurrences of a specified value with another value in a given Span<T>.

+

FindAllOffsetsOfByte

+
+

Missing SIMD path for non-x86/x64 platforms. PRs are welcome.

+
+

public static List<int> FindAllOffsetsOfByte(this ReadOnlySpan<byte> data, byte value)
+public static List<int> FindAllOffsetsOfByte(this ReadOnlySpan<byte> data, byte value, int offsetCountHint)
+
+Finds all the offsets of a given byte value in a target ReadOnlySpan<byte> instance.
+The second overload allows specifying an optional offsetCountHint parameter to preallocate the list capacity.

+

Usage

+

Get Reference without Bounds Checks

+
Span<int> span = new int[] { 1, 2, 3 };
+ref int firstElement = ref span.DangerousGetReference();
+
+

Get Reference at Specific Index without Bounds Checks

+
Span<int> span = new int[] { 1, 2, 3 };
+ref int elementAtTwo = ref span.DangerousGetReferenceAt(2);
+
+

Convert Span to Byte Span

+
Span<int> intSpan = new int[] { 1, 2, 3 };
+Span<byte> byteSpan = intSpan.AsBytes();
+
+

Cast Span

+
Span<byte> byteSpan = new byte[] { 1, 2, 3, 4 };
+Span<int> intSpan = byteSpan.Cast<byte, int>();
+
+

Find Index of an Element

+
Span<int> span = new int[] { 1, 2, 3, 4, 5 };
+ref int value = ref span[3];
+int index = span.IndexOf(ref value); // index = 3
+
+

Count Occurrences of a Value

+
Span<int> span = new int[] { 1, 2, 2, 3, 2 };
+int count = span.Count(2); // 3
+
+

Slice Span Without Bounds Checks

+
Span<int> span = new int[] { 1, 2, 3, 4, 5 };
+Span<int> slicedSpan = span.SliceFast(1, 3);
+
+

Replace Elements in a Span

+
Span<char> span = "hello world".ToCharArray();
+Span<char> buffer = new char[span.Length];
+Span<char> replacedSpan = span.Replace('l', 'x', buffer);
+
+

Find All Offsets of a Byte

+
byte[] data = new byte[] { 1, 2, 3, 2, 4, 2 };
+ReadOnlySpan<byte> span = data;
+List<int> offsets = span.FindAllOffsetsOfByte(2);
+
+

Find All Offsets of a Byte with Offset Count Hint

+
byte[] data = new byte[] { 1, 2, 3, 2, 4, 2 };
+ReadOnlySpan<byte> span = data;
+List<int> offsets = span.FindAllOffsetsOfByte(2, 3);
+
+ + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/Extensions/StreamExtensions/index.html b/Extensions/StreamExtensions/index.html new file mode 100644 index 0000000..7103a77 --- /dev/null +++ b/Extensions/StreamExtensions/index.html @@ -0,0 +1,1338 @@ + + + + + + + + + + + + + + + + + + + + + + + + Stream - Reloaded Memory Library + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + + + + + +
+
+ + + + + + + + +

StreamExtensions

+
+

Utility class providing high performance extension methods for working with Stream objects.

+
+

StreamExtensions is a utility class that provides extension methods for the Stream type, including padding, writing, and reading unmanaged and marshalled structures.

+

Methods

+

AddPadding

+

public static void AddPadding<TStream>(this TStream stream, int alignment)
+
+Pads the stream with any/random bytes until it is aligned to the specified alignment. The padding bytes depend on the implementation of Stream.SetLength.

+

AddPadding

+

public static void AddPadding<TStream>(this TStream stream, byte value, int alignment = 2048)
+
+Pads the stream with the specified value bytes until it is aligned to the specified alignment.

+

Write

+

public static void Write<TStream, T>(this TStream stream, Span<T> structure) where T : unmanaged
+
+Appends an unmanaged structure onto the given stream and advances the position.

+

Write

+

public static void Write<TStream, T>(this TStream stream, in T structure) where T : unmanaged
+
+Appends an unmanaged structure onto the given stream and advances the position.

+

WriteMarshalled

+

public static void WriteMarshalled<TStream, T>(this TStream stream, T item)
+
+Appends a managed/marshalled structure onto the given stream and advances the position.

+

WriteMarshalled

+

public static void WriteMarshalled<TStream, T>(this TStream stream, T[] item)
+
+Appends an array of managed/marshalled structures onto the given stream and advances the position.

+

WriteMarshalled

+

public static void WriteMarshalled<TStream, T>(this TStream stream, Span<T> item)
+
+Appends a span of managed/marshalled structures onto the given stream and advances the position.

+

Read

+

public static void Read<TStream, T>(this TStream stream, out T result) where T : unmanaged
+
+Reads a single unmanaged structure of type T from the stream.

+

Read

+

public static void Read<TStream, T>(this TStream stream, T[] output) where T : unmanaged
+
+Reads a span of unmanaged structures of type T from the stream into the provided output array.

+

Read

+

public static void Read<TStream, T>(this TStream stream, Span<T> output) where T : unmanaged
+
+Reads a span of unmanaged structures of type T from the stream into the provided output span.

+

ReadMarshalled

+

public static void ReadMarshalled<TStream, T>(this TStream stream, out T result)
+
+Reads a single marshalled structure of type T from the stream.

+

ReadMarshalled

+

public static void ReadMarshalled<TStream, T>(this TStream stream, T[] output)
+
+Reads a span of marshalled structures of type T from the stream into the provided output array.

+

ReadMarshalled

+

public static void ReadMarshalled<TStream, T>(this TStream stream, Span<T> output)
+
+Reads a span of marshalled structures of type T from the stream into the provided output span.

+

Usage

+

Pad Stream with Random Bytes

+
using var stream = new MemoryStream();
+stream.AddPadding(4096);
+
+

Pad Stream with Specific Byte Value

+
using var stream = new MemoryStream();
+stream.AddPadding(0xFF, 4096);
+
+

Write Unmanaged Structure

+
using var stream = new MemoryStream();
+Vector2 structure = new Vector2(1, 2);
+stream.Write(structure);
+
+

Write Marshalled Structure

+
using var stream = new MemoryStream();
+MyStruct item = new MyStruct { Value1 = 1, Value2 = "Hello" };
+stream.WriteMarshalled(item);
+
+

Read Unmanaged Structure

+
using var stream = new MemoryStream();
+stream.Read(out Vector2 result);
+
+

Read Marshalled Structure

+
using var stream = new MemoryStream();
+stream.ReadMarshalled(out MyStruct result);
+
+

Read Span of Unmanaged Structures

+
using var stream = new MemoryStream();
+Vector2[] output = new Vector2[10];
+stream.Read(output);
+
+

Read Span of Marshalled Structures

+
using var stream = new MemoryStream();
+MyStruct[] output = new MyStruct[10];
+stream.ReadMarshalled(output);
+
+ + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/Extensions/StringExtensions/index.html b/Extensions/StringExtensions/index.html new file mode 100644 index 0000000..ee12f4b --- /dev/null +++ b/Extensions/StringExtensions/index.html @@ -0,0 +1,1295 @@ + + + + + + + + + + + + + + + + + + + + + + + + String - Reloaded Memory Library + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + + + + + +
+
+ + + + + + + + +

StringExtensions

+
+

Partially forked from Community Toolkit.

+
+
+

Utility class providing high performance extension methods for working with the string type.

+
+

StringExtensions is a utility class that provides extension methods for the string type, including getting references to string elements, and counting the number of occurrences of a character in a string.

+

Methods

+

DangerousGetReference

+
public static ref char DangerousGetReference(this string text)
+
+

Returns a reference to the first element within a given string, with no bounds checks. It is the caller's responsibility to perform bounds checks when dereferencing the returned value.

+

DangerousGetReferenceAt

+
public static ref char DangerousGetReferenceAt(this string text, int i)
+
+

Returns a reference to an element at a specified index within a given string, with no bounds checks. It is the caller's responsibility to ensure the i parameter is valid.

+

Count

+
public static int Count(this string text, char c)
+
+

Counts the number of occurrences of a given character in a target string instance.

+

GetHashCodeFast

+
+

SIMD method currently restricted to .NET 7+. PRs for backports are welcome.

+
+
+

Will produce different hashes depending on runtime or CPU.

+
+
+

Optimised for File Paths specifically

+
+
public static nuint GetHashCodeFast(string text)
+public static unsafe nuint GetHashCodeFast(this ReadOnlySpan<char> text)
+
+

Faster hashcode for strings; but does not randomize between application runs.

+

Use this method if and only if 'Denial of Service' attacks are not a concern +(i.e. never used for free-form user input), or are otherwise mitigated.

+

This method does not provide guarantees about producing the same hash across different machines or library versions, +or runtime; only for the current process. Instead, it prioritises speed over all.

+

GetHashCodeLowerFast

+
+

SIMD method currently restricted to .NET 7+. PRs for backports are welcome.

+
+
+

Will produce different hashes depending on runtime or CPU.

+
+
+

Optimised for File Paths specifically

+
+
public static nuint GetHashCodeLowerFast(this string text)
+public static unsafe nuint GetHashCodeLowerFast(this ReadOnlySpan<char> text)
+
+

Faster hashcode for strings, hashed in lower (invariant) case; does not randomize between application runs.

+

Use this method if and only if 'Denial of Service' attacks are not a concern +(i.e. never used for free-form user input), or are otherwise mitigated.

+

This method does not provide guarantees about producing the same hash across different machines or library versions, +or runtime; only for the current process. Instead, it prioritises speed over all.

+

ToLowerInvariantFast

+
public static string ToLowerInvariantFast(this string text)
+public static unsafe void ToLowerInvariantFast(this ReadOnlySpan<char> text, Span<char> target)
+
+

Converts the given string to lower case (invariant casing) using the fastest possible implementation. +This method is optimized for performance but currently has limitations for short non-ASCII inputs.

+

ToUpperInvariantFast

+
public static string ToUpperInvariantFast(this string text)
+public static unsafe void ToUpperInvariantFast(this ReadOnlySpan<char> text, Span<char> target)
+
+

Converts the given string to upper case (invariant casing) using the fastest possible implementation. +This method is optimized for performance but currently has limitations for short non-ASCII inputs.

+

Usage

+

Get Reference to First Element in String

+
string text = "Hello, world!";
+ref char firstCharRef = ref text.DangerousGetReference();
+
+

Get Reference to Element at Index in String

+
string text = "Hello, world!";
+int index = 4;
+ref char charAtIndexRef = ref text.DangerousGetReferenceAt(index);
+
+

Count Character Occurrences in String

+
string text = "Hello, world!";
+char targetChar = 'l';
+int count = text.Count(targetChar);
+
+

Get Fast Hash Code

+
string text = "Hello, world!";
+nuint fastHashCode = text.GetHashCodeFast();
+
+

Get Lower Case Hash Code

+
string text = "Hello, World!";
+nuint lowerCaseHashCode = text.GetHashCodeLowerFast();
+
+

Convert String to Lower Case Invariant Fast

+
string text = "Hello, WORLD!";
+string lowerInvariant = text.ToLowerInvariantFast(); // hello, world!
+
+

Convert String to Upper Case Invariant Fast

+
string text = "hello, world!";
+string upperInvariant = text.ToUpperInvariantFast(); // HELLO, WORLD!
+
+

Convert ReadOnlySpan to Lower Case Invariant Fast

+
string text = "Hello, WORLD!";
+Span<char> target = stackalloc char[textSpan.Length]; // Careful with string length!
+text.AsSpan().ToLowerInvariantFast(target); // hello, world! (on stack)
+
+

Convert ReadOnlySpan to Upper Case Invariant Fast

+
string text = "hello, world!";
+Span<char> target = stackalloc char[textSpan.Length]; // Careful with string length!
+text.AsSpan().ToLowerInvariantFast(target); // HELLO, WORLD! (on stack)
+
+ + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/Extensions/VectorExtensions/index.html b/Extensions/VectorExtensions/index.html new file mode 100644 index 0000000..5752010 --- /dev/null +++ b/Extensions/VectorExtensions/index.html @@ -0,0 +1,1033 @@ + + + + + + + + + + + + + + + + + + + + + + + + Vector - Reloaded Memory Library + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

VectorExtensions

+
+

Utility class providing high performance extension methods for working with the Vector struct.

+
+

VectorExtensions is a utility class that provides extension methods for the Vector struct.

+

Methods

+

LoadUnsafe

+
internal static Vector<T> LoadUnsafe<T>(ref T source, nuint elementOffset) where T : struct
+
+

Loads an element at a specified offset into a vector. Unsafe operations are used for performance reasons.

+

StoreUnsafe

+
internal static void StoreUnsafe<T>(this Vector<T> source, ref T destination, nuint elementOffset) where T : struct
+
+

Stores an element from a vector into the destination + offset. Unsafe operations are used for performance reasons.

+

Usage

+

Load Element into a Vector at an Offset

+
int[] array = new int[] { 1, 2, 3, 4, 5 };
+ref int source = ref array[0];
+nuint elementOffset = 2;
+Vector<int> vector = VectorExtensions.LoadUnsafe(ref source, elementOffset);
+
+

Store Element from a Vector to Destination + Offset

+
Vector<int> vector = new Vector<int>(new int[] { 1, 2, 3, 4 });
+int[] destinationArray = new int[vector.Count];
+ref int destination = ref destinationArray[0];
+nuint elementOffset = 1;
+vector.StoreUnsafe(ref destination, elementOffset);
+
+ + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/Pointers/FixedArrayPtr/index.html b/Pointers/FixedArrayPtr/index.html new file mode 100644 index 0000000..cece1e2 --- /dev/null +++ b/Pointers/FixedArrayPtr/index.html @@ -0,0 +1,1096 @@ + + + + + + + + + + + + + + + + + + + + + + + + FixedArrayPtr<T> - Reloaded Memory Library + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

FixedArrayPtr<T> and MarshalledFixedArrayPtr<T>

+
+

Abstraction for a pointer to a value of type T with a known length.

+
+
+

Zero overhead but not 1:1 codegen in all scenarios. e.g. Multiplying an element in place via Setter can be slower (.NET 7).

+
+

A helper to allow you to manage a collection of items in unmanaged, static memory; for example, find an item.

+

Properties

+
    +
  • Pointer: A Ptr representing the memory address of the first element in the fixed-size array.
  • +
  • Count: The number of elements in the fixed-size array.
  • +
  • ArraySize: The total size in bytes of the fixed-size array.
  • +
+

Examples

+

Initialization

+
var ptr = new FixedArrayPtr<int>(address, count);
+
+
    +
  • Address: The memory address of the first element in the fixed-size array.
  • +
  • Count: The number of elements in the fixed-size array.
  • +
+

Element Access

+
+

The following methods should be used with in memory/RAM addresses. See Memory Read/Write for APIs that work with ICanReadWriteMemory implementations.

+
+
ref T AsRef(int index);
+T Get(int index);
+void Get(int index, out T value);
+void Set(int index, in T value);
+
+

These methods provide access to individual elements in the fixed-size array. The AsRef() method returns a reference to +an element, allowing for direct modification of the element's value. The Get() and Set() methods retrieve and update +the values of elements at specified indices.

+

Memory Read/Write

+

T Get<TSource>(TSource source, int index);
+void Get<TSource>(TSource source, int index, out T value);
+void Set<TSource>(TSource source, int index, in T value);
+
+These methods provide access to individual elements in the fixed-size array, allowing read and write operations to be +performed on an implementation of ICanReadWriteMemory. This can be useful when working with external processes or +other memory sources.

+

Copying

+
void CopyFrom(Span<T> sourceArray, int length);
+void CopyFrom(Span<T> sourceArray, int length, int sourceIndex, int destinationIndex);
+void CopyTo(Span<T> destinationArray, int length);
+void CopyTo(Span<T> destinationArray, int length, int sourceIndex, int destinationIndex);
+
+

These methods provide copying functionality between the fixed-size array and managed arrays. CopyFrom() copies elements +from a managed array to the fixed-size array, and CopyTo() copies elements from the fixed-size array to a managed array.

+

Both methods support copying a specified number of elements, as well as specifying source and destination indices for +the copy operation.

+ +
bool Contains(in T item);
+bool Contains<TSource>(TSource source, in T item);
+int IndexOf(in T item);
+int IndexOf<TSource>(TSource source, in T item);
+
+

These methods provide search functionality for the fixed-size array, allowing you to check for the existence of an element +or find its index. The Contains() methods return true if the specified item is found in the array, and the IndexOf() methods +return the index of the first occurrence of the specified item or -1 if the item is not found.

+

SourcedFixedArrayPtr<T>

+
+

This is a tuple of FixedArrayPtr<T> and TSource.

+
+

API surface is the same, all methods are delegated to underlying FixedArrayPtr<T>.

+

Notably however, this API enables the use of LINQ; i.e. the following are now valid:

+
foreach (int value in sourcedFixedArrayPtr)
+{
+    // ...
+}
+
+
sourcedFixedArrayPtr.Max(x => x);
+
+

etc.

+ + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/Pointers/Ptr/index.html b/Pointers/Ptr/index.html new file mode 100644 index 0000000..719e6bc --- /dev/null +++ b/Pointers/Ptr/index.html @@ -0,0 +1,1128 @@ + + + + + + + + + + + + + + + + + + + + + + + + Ptr<T> - Reloaded Memory Library + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Ptr<T> and MarshalledPtr<T>

+
+

Abstraction for a pointer to a value of type T.

+
+
+

This type was formerly called BlittablePointer<T> and ArrayPtr<T> in old library versions.

+
+
+

Zero overhead but not 1:1 codegen in all scenarios. e.g. Multiplying an element in place via Setter can be slower (.NET 7).

+
+

A helper to allow you to do two things:

+
    +
  • Use pointer arithmetic on anything implementing ICanReadWriteMemory. (e.g. Memory of External Process).
  • +
  • To use in generics.
  • +
+

The type MarshalledPtr<T> also exists, this is a special type of Ptr<T> that marshals the elements as they are read/written; +with pointer arithmetic being performed on the marshalled size of the object rather than the raw size.

+

Examples

+
+

Basically, the Ptr<T> type is just a regular pointer, with all of the operations you would expect from a pointer; except that it can be used in Generics, and also read/write to more than just RAM.

+
+

Initialization

+
+

The Ptr<T> type supports implicit conversions to/from raw pointers.

+
+
int someValue = 42;
+Ptr<int> ptr = &someValue;
+int* ptr2 = intPtr;
+
+

AsRef

+
+

Pointers can be converted for references.

+
+
ref int valueFromPtr = ref intPtr.AsRef();
+Console.WriteLine($"Value from pointer: {valueFromPtr}");
+
+

This can be especially useful for game modding APIs, the end user can for example do this:

+
ref var playerCount = ref State.NumberOfPlayers.AsRef();
+playerCount = 5;
+
+

Completely avoiding pointer arithmetic; which is friendly to non-programmers.

+

Pointer Arithmetic

+
+

You can do regular arithmetic on pointers, e.g. add 1 to go to next value.

+
+
Ptr<int> arrayIntPtr = arrayPtr;
+Ptr<int> offsetArrayIntPtr = arrayIntPtr + 2;
+
+Console.WriteLine($"Value at original pointer: {arrayIntPtr.AsRef()}"); // Output: Value at original pointer: 1
+Console.WriteLine($"Value at offset pointer: {offsetArrayIntPtr.AsRef()}"); // Output: Value at offset pointer: 3
+Console.WriteLine($"Equal? {offsetArrayIntPtr != arrayIntPtr}"); // Equal? false
+
+// You can also do ++ and --
+arrayIntPtr++;
+arrayIntPtr++;
+
+// Now arrayIntPtr points to the third element in the array.
+
+

Value Read / Write

+
+

You can read/write values with an implementation of ICanReadWriteMemory

+
+

Reading from RAM:

+
int valueFromSource = pointer.Get(); // implicit Memory.Instance
+Console.WriteLine($"Value from RAM: {valueFromSource}");
+
+

Reading from RAM of another process:

+
// externalMemory = new ExternalMemory(anotherProcess);
+int valueFromSource = pointer.Get(externalMemory);
+Console.WriteLine($"Value from another process' RAM: {valueFromSource}");
+
+

You can also read/write to offsets:

+
int valueAtOffset2 = pointer.Get(2);
+Console.WriteLine($"Value from RAM (Offset 2): {valueAtOffset2}");
+
+

Branch on Null Pointer

+
+

Just like in C, you can branch into an if statement if a pointer isn't null.

+
+
var notNullPointer = new Ptr<int>((int*)0x12345678);
+if (notNullPointer)
+    Console.WriteLine("Pointer is not null!");
+
+

From External Libraries

+

Getting a ref to native memory/pointer:

+
// Defined in a library for modding a certain hoverboard racing game.
+public static readonly Ptr<int> NumberOfRacers = new Ptr<int>((int*)0x64B758);
+
+// End user can do either
+int* racers = NumberOfRacers;
+
+// or avoid pointer arithmetic entirely.
+ref int racers = ref NumberOfRacers.AsRef();
+
+

Hooking a function with Reloaded.Hooks:

+
// Function pointer declatation (can also use delegate).
+[Function(CallingConventions.MicrosoftThiscall)]
+public struct OpenFileFnPtr { public FuncPtr<Ptr<byte>, Ptr<byte>, int, Ptr<byte>> Value; }
+
+_openFile = FileSystemFuncs.OpenFile.HookAs<FileSystemFuncs.OpenFileFnPtr>(typeof(FileAccessServer), nameof(OpenBfsFileImpl)).Activate();
+
+

SourcedPtr<T>

+
+

This is a tuple of Ptr<T> and TSource.

+
+

Basically, it allows you to assign a TSource to a Ptr<T> and skip passing TSource as a parameter.

+

Remaining usage is the same.

+ + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/Reloaded/Images/Contribute/ForkTheRepo.png b/Reloaded/Images/Contribute/ForkTheRepo.png new file mode 100644 index 0000000..db1f529 Binary files /dev/null and b/Reloaded/Images/Contribute/ForkTheRepo.png differ diff --git a/Reloaded/Images/Contribute/GitHubDesktop.png b/Reloaded/Images/Contribute/GitHubDesktop.png new file mode 100644 index 0000000..75b8f71 Binary files /dev/null and b/Reloaded/Images/Contribute/GitHubDesktop.png differ diff --git a/Reloaded/Images/Contribute/LocalRun.png b/Reloaded/Images/Contribute/LocalRun.png new file mode 100644 index 0000000..d15f556 Binary files /dev/null and b/Reloaded/Images/Contribute/LocalRun.png differ diff --git a/Reloaded/Images/Contribute/OpenPR.png b/Reloaded/Images/Contribute/OpenPR.png new file mode 100644 index 0000000..e2d1aba Binary files /dev/null and b/Reloaded/Images/Contribute/OpenPR.png differ diff --git a/Reloaded/Images/Contribute/OpenPullRequest.png b/Reloaded/Images/Contribute/OpenPullRequest.png new file mode 100644 index 0000000..e2d1aba Binary files /dev/null and b/Reloaded/Images/Contribute/OpenPullRequest.png differ diff --git a/Reloaded/Images/Contribute/Rider.png b/Reloaded/Images/Contribute/Rider.png new file mode 100644 index 0000000..27f380c Binary files /dev/null and b/Reloaded/Images/Contribute/Rider.png differ diff --git a/Reloaded/Images/Nexus-Heart-40.png b/Reloaded/Images/Nexus-Heart-40.png new file mode 100644 index 0000000..3337565 Binary files /dev/null and b/Reloaded/Images/Nexus-Heart-40.png differ diff --git a/Reloaded/Images/Nexus-Heart.png b/Reloaded/Images/Nexus-Heart.png new file mode 100644 index 0000000..43f7a26 Binary files /dev/null and b/Reloaded/Images/Nexus-Heart.png differ diff --git a/Reloaded/Images/Nexus-Heart.psd b/Reloaded/Images/Nexus-Heart.psd new file mode 100644 index 0000000..473c865 Binary files /dev/null and b/Reloaded/Images/Nexus-Heart.psd differ diff --git a/Reloaded/Images/Nexus-Icon-40.png b/Reloaded/Images/Nexus-Icon-40.png new file mode 100644 index 0000000..8781822 Binary files /dev/null and b/Reloaded/Images/Nexus-Icon-40.png differ diff --git a/Reloaded/Images/Nexus-Icon.png b/Reloaded/Images/Nexus-Icon.png new file mode 100644 index 0000000..3e611b4 Binary files /dev/null and b/Reloaded/Images/Nexus-Icon.png differ diff --git a/Reloaded/Images/Reloaded-Heart-40.png b/Reloaded/Images/Reloaded-Heart-40.png new file mode 100644 index 0000000..6fdf9da Binary files /dev/null and b/Reloaded/Images/Reloaded-Heart-40.png differ diff --git a/Reloaded/Images/Reloaded-Heart.png b/Reloaded/Images/Reloaded-Heart.png new file mode 100644 index 0000000..0ed75b3 Binary files /dev/null and b/Reloaded/Images/Reloaded-Heart.png differ diff --git a/Reloaded/Images/Reloaded-Icon-40.png b/Reloaded/Images/Reloaded-Icon-40.png new file mode 100644 index 0000000..9a43d61 Binary files /dev/null and b/Reloaded/Images/Reloaded-Icon-40.png differ diff --git a/Reloaded/Images/Reloaded-Icon.png b/Reloaded/Images/Reloaded-Icon.png new file mode 100644 index 0000000..ae0d6d2 Binary files /dev/null and b/Reloaded/Images/Reloaded-Icon.png differ diff --git a/Reloaded/Images/Reloaded-Templates.7z b/Reloaded/Images/Reloaded-Templates.7z new file mode 100644 index 0000000..371a063 Binary files /dev/null and b/Reloaded/Images/Reloaded-Templates.7z differ diff --git a/Reloaded/LICENSE b/Reloaded/LICENSE new file mode 100644 index 0000000..7de5f64 --- /dev/null +++ b/Reloaded/LICENSE @@ -0,0 +1,779 @@ +# The Reloaded Project License + +Components of the Reloaded-Project are governed by the *GPLv3* license as of May 2023. +Prior versions of the project were under the LGPLv3 license. + +The complete license text can be found at the end of this document. + +This FAQ is meant to clarify our licensing choice and its implications. +Please note, though, that the full license text is the final legal authority. + +## Why was GPL v3 chosen? + +The primary objective is to prevent closed-source, commercial exploitation of the project. +We want to ensure that the project isn't used within a proprietary environment for +profit-making purposes such as: + +- Being sold behind a Patreon paywall. +- Being integrated into a closed-source commercial product for sale. + +The Reloaded Project is a labour of love from unpaid hobbyist volunteers. +It wasn't designed for commercial use, and exploiting it for profit feels fundamentally unfair. + +While the GPLv3 license doesn't prohibit commercial use outright, it does prevent commercial +exploitation by requiring that contributions are given back to the open-source community. + +In that fashion, everyone can benefit from the projects under the Reloaded label. + +## Can I use Reloaded Libraries Commercially? + +You can as long as the resulting produce is also licensed under GPLv3, and thus open source. + +## Can I use Reloaded Libraries in a closed-source application? + +The license terms do not permit this. + +However, if your software is completely non-commercial, meaning it's neither +sold for profit, funded in development, nor hidden behind a paywall (like Patreon), +we will just look the other way. + +This often applies to non-professional programmers, learners, or those +with no intent to exploit the project. We believe in understanding and +leniency for those who might not know better. + +GPL v3 exists to protect the project and its contributors. +If you're not exploiting the project for commercial gain, you're not hurting us; +and we will not enforce the terms of the GPL. + +If you are interested in obtaining a commercial license, or want an explicit written exemption, +please get in touch with the repository owners. + +## Can I link Reloaded Libraries statically/dynamically? + +Yes, as long as you adhere to the GPLv3 license terms, you're permitted to statically +link Reloaded Libraries into your project, for instance, through the use of NativeAOT or ILMerge. + +## Guidelines for Non-Commercial Use + +We support and encourage the non-commercial use of Reloaded Libraries. +Non-commercial use generally refers to the usage of our libraries for personal projects, +educational purposes, academic research, or use by non-profit organizations. + +**Personal Projects:** You're free to use our libraries for projects that you undertake +for your own learning, hobby or personal enjoyment. This includes creating mods for your +favorite games or building your own applications for personal use. + +**Educational Use:** Teachers and students are welcome to use our libraries as a learning +resource. You can incorporate them into your teaching materials, student projects, coding +bootcamps, workshops, etc. + +**Academic Research:** Researchers may use our libraries for academic and scholarly research. +We'd appreciate if you cite our work in any publications that result from research involving our libraries. + +**Non-profit Organizations:** If you're part of a registered non-profit organization, +you can use our libraries in your projects. However, any derivative work that uses our +libraries must also be released under the GPL. + +Please remember, if your usage of our libraries evolves from non-commercial to commercial, +you must ensure compliance with the terms of the GPL v3 license. + +## Attribution Requirements + +As Reloaded Project is a labor of love, done purely out of passion and with an aim to contribute +to the broader community, we highly appreciate your support in providing attribution when using +our libraries. While not legally mandatory under the GPL v3, it is a simple act that can go a long +way in recognizing the efforts of our contributors and fostering an open and collaborative atmosphere. + +If you choose to provide attribution (and we hope you do!), here are some guidelines: + +- **Acknowledge the Use of Reloaded Libraries:** Mention that your project uses or is based on Reloaded libraries. + This could be in your project's readme, a credits page on a website, a manual, or within the software itself. + +- **Link to the Project:** If possible, provide a link back to the Reloaded Project. + This allows others to explore and potentially benefit from our work. + +Remember, attribution is more than just giving credit,,, it's a way of saying thank you 👉👈, fostering reciprocal +respect, and acknowledging the power of collaborative open-source development. + +We appreciate your support and look forward to seeing what amazing projects you create using Reloaded libraries! + +## Code from MIT/BSD Licensed Projects + +In some rare instances, code from more permissively licensed projects, such as those under the +`MIT` or `BSD` licenses, may be referenced, incorporated, or slightly modified within the Reloaded Project. + +It's important to us to respect the terms and intentions of these permissive licenses, +which often allow their code to be used in a wide variety of contexts, including in GPL-licensed projects like ours. + +In these cases, the Reloaded Project is committed to clearly disclosing the usage of such code: + +- **Method-Level Disclosure:** For individual methods or small code snippets, we use appropriate + attribution methods, like programming language attributes. For example, methods borrowed or adapted + from MIT-licensed projects might be marked with a `[MITLicense]` attribute. + +- **File-Level Disclosure:** For larger amounts of code, such as entire files or modules, we'll include + the original license text at the top of the file and clearly indicate which portions of the code originate + from a differently-licensed project. + +- **Project-Level Disclosure:** If an entire library or significant portion of a project under a more permissive + license is used, we will include an acknowledgment in a prominent location, such as the readme file or the + project's license documentation. + +This approach ensures we honor the contributions of the open source community at large, respect the original +licenses, and maintain transparency with our users about where code originates from. + +Any files/methods or snippets marked with those attributes may be consumed using their original license terms. +i.e. If a method is marked with `[MITLicense]`, you may use it under the terms of the MIT license. + +## Contributing to the Reloaded Project + +We welcome and appreciate contributions to the Reloaded Project! +By contributing, you agree to share your changes under the same GPLv3 license, +helping to make the project better for everyone. + +------------------------ +# Reloaded.Memory + + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + +Copyright (C) 2007 Free Software Foundation, Inc. +Everyone is permitted to copy and distribute verbatim copies +of this license document, but changing it is not allowed. + + Preamble + +The GNU General Public License is a free, copyleft license for +software and other kinds of works. + +The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + +When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + +To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + +For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + +Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + +For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + +Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + +Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + +The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + +0. Definitions. + +"This License" refers to version 3 of the GNU General Public License. + +"Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + +"The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + +To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + +A "covered work" means either the unmodified Program or a work based +on the Program. + +To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + +To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + +An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + +1. Source Code. + +The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + +A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + +The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + +The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + +The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + +The Corresponding Source for a work in source code form is that +same work. + +2. Basic Permissions. + +All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + +You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + +Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + +3. Protecting Users' Legal Rights From Anti-Circumvention Law. + +No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + +When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + +4. Conveying Verbatim Copies. + +You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + +You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + +5. Conveying Modified Source Versions. + +You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + +A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + +6. Conveying Non-Source Forms. + +You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + +A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + +A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + +"Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + +If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + +The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + +Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + +7. Additional Terms. + +"Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + +When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + +Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + +All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + +If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + +Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + +8. Termination. + +You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + +However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + +Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + +Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + +9. Acceptance Not Required for Having Copies. + +You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + +10. Automatic Licensing of Downstream Recipients. + +Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + +An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + +You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + +11. Patents. + +A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + +A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + +Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + +In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + +If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + +If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + +A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + +Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + +12. No Surrender of Others' Freedom. + +If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + +13. Use with the GNU Affero General Public License. + +Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + +14. Revised Versions of this License. + +The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + +If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + +Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + +15. Disclaimer of Warranty. + +THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + +16. Limitation of Liability. + +IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + +17. Interpretation of Sections 15 and 16. + +If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + +------------------------ +# .NET Community Toolkit + +Copyright © .NET Foundation and Contributors + +All rights reserved. + +## MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +documentation files (the “Software”), to deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of +the Software. + +THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS +OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/Reloaded/Pages/contributing/index.html b/Reloaded/Pages/contributing/index.html new file mode 100644 index 0000000..96b6dfd --- /dev/null +++ b/Reloaded/Pages/contributing/index.html @@ -0,0 +1,946 @@ + + + + + + + + + + + + + + + + + + + + Contributing to the Wiki: Locally - Reloaded Memory Library + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Contributing to the Wiki: Locally

+
+

Info

+

This page shows you how to contribute to any documentation page or wiki +based on this template.

+
+
+

Note

+

This theme is forked from my theme for Nexus Docs; +and this page is synced with that.

+
+

Tutorial

+
+

Note

+

If you are editing the repository with the theme itself on Windows, it might be a good idea to run +git config core.symlinks true first to allow git to create symlinks on clone.

+
+

You should learn the basics of git, an easy way is to give GitHub Desktop (Tutorial) a go.
+It's only 15 minutes 😀.

+
    +
  1. Create a GitHub account.
  2. +
  3. +

    Fork this repository:

    +

    Image

    +

    This will create a copy of the repository on your own user account, which you will be able to edit.

    +
  4. +
  5. +

    Clone this repository.

    +

    For example, using GitHub Desktop: +Image

    +
  6. +
  7. +

    Make changes inside the docs folder.

    +

    Image

    +

    Consider using a Markdown Cheat Sheet if you are new to markdown.

    +

    I recommend using a markdown editor such as Typora.
    +Personally I just work from inside Rider.

    +
  8. +
  9. +

    Commit the changes and push to GitHub.

    +
  10. +
  11. +

    Open a Pull Request.

    +

    Image

    +

    Opening a Pull Request will allow us to review your changes before adding them with the main official page. If everything's good, we'll hit the merge button and add your changes to the official repository.

    +
  12. +
+

Website Live Preview

+

If you are working on the wiki locally, you can generate a live preview the full website. +Here's a quick guide of how you could do it from your command prompt (cmd).

+
    +
  1. +

    Install Python 3

    +

    If you have winget installed, or Windows 11, you can do this from the command prompt. +

    winget install Python.Python.3
    +

    +

    Otherwise download Python 3 from the official website or package manager.

    +
  2. +
  3. +

    Install Material for MkDocs and Plugins (Python package) +

    # Restart your command prompt before running this command.
    +pip install mkdocs-material
    +pip install mkdocs-redirects
    +

    +
  4. +
  5. +

    Open a command prompt in the folder containing mkdocs.yml. and run the site locally. +

    # Move to project folder.
    +cd <Replace this with full path to folder containing `mkdocs.yml`>
    +mkdocs serve
    +

    +

    Image

    +

    Copy the address to your web browser and enjoy the live preview; any changes you save will be shown instantly.

    +
  6. +
+ + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/Reloaded/Pages/index.html b/Reloaded/Pages/index.html new file mode 100644 index 0000000..0253322 --- /dev/null +++ b/Reloaded/Pages/index.html @@ -0,0 +1,1020 @@ + + + + + + + + + + + + + + + + + + + + Index - Reloaded Memory Library + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + + + +
+
+
+ + + + +
+
+
+ + + + + + + + + +
+
+ + + + + + + + +

Index

+ +
+

The Reloaded MkDocs Theme

+ +

+ A Theme for MkDocs Material. +
+ That resembles the look of Reloaded. +
+ +

About

+

This it the NexusMods theme for Material-MkDocs, inspired by the look of Reloaded-II.

+

The overall wiki theme should look fairly close to the actual launcher appearance.

+

Setup From Scratch

+
    +
  • Add this repository as submodule to docs/Reloaded.
  • +
  • Save the following configuration as mkdocs.yml in your repository root.
  • +
+
site_name: Reloaded MkDocs Theme
+site_url: https://github.com/Reloaded-Project/Reloaded.MkDocsMaterial.Themes.R2
+
+repo_name: Reloaded-Project/Reloaded.MkDocsMaterial.Themes.R2
+repo_url: https://github.com/Reloaded-Project/Reloaded.MkDocsMaterial.Themes.R2
+
+extra:
+  social:
+    - icon: fontawesome/brands/github
+      link: https://github.com/Reloaded-Project
+    - icon: fontawesome/brands/twitter
+      link: https://twitter.com/thesewer56?lang=en-GB
+
+extra_css:
+  - Reloaded/Stylesheets/extra.css
+
+markdown_extensions:
+  - admonition
+  - tables
+  - pymdownx.details
+  - pymdownx.highlight
+  - pymdownx.superfences:
+      custom_fences:
+        - name: mermaid
+          class: mermaid
+          format: !!python/name:pymdownx.superfences.fence_code_format
+  - pymdownx.tasklist
+  - def_list
+  - meta
+  - md_in_html
+  - attr_list
+  - footnotes
+  - pymdownx.tabbed:
+      alternate_style: true
+  - pymdownx.emoji:
+      emoji_index: !!python/name:materialx.emoji.twemoji
+      emoji_generator: !!python/name:materialx.emoji.to_svg
+
+theme:
+  name: material
+  palette:
+    scheme: reloaded-slate
+  features:
+    - navigation.instant
+
+plugins:
+  - search
+
+nav:
+  - Home: index.md
+
+
    +
  • Add a GitHub Actions workload in .github/workflows/DeployMkDocs.yml.
  • +
+
name: DeployMkDocs
+
+# Controls when the action will run. 
+on:
+  # Triggers the workflow on push on the master branch
+  push:
+    branches: [ main ]
+
+  # Allows you to run this workflow manually from the Actions tab
+  workflow_dispatch:
+
+# A workflow run is made up of one or more jobs that can run sequentially or in parallel
+jobs:
+  # This workflow contains a single job called "build"
+  build:
+    # The type of runner that the job will run on
+    runs-on: ubuntu-latest
+
+    # Steps represent a sequence of tasks that will be executed as part of the job
+    steps:
+
+      # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
+      - name: Checkout Branch
+        uses: actions/checkout@v2
+        with:
+          submodules: recursive
+
+      # Deploy MkDocs
+      - name: Deploy MkDocs
+        # You may pin to the exact commit or the version.
+        # uses: mhausenblas/mkdocs-deploy-gh-pages@66340182cb2a1a63f8a3783e3e2146b7d151a0bb
+        uses: mhausenblas/mkdocs-deploy-gh-pages@master
+        env:
+          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+          REQUIREMENTS: ./docs/requirements.txt
+
+
    +
  • Push to GitHub, this should produce a GitHub Pages site.
  • +
  • Go to Settings -> Pages in your repo and select gh-pages branch to enable GitHub pages.
  • +
+

Your page should then be live.

+
+

Tip

+

Refer to Contributing for instructions on how to locally edit and modify the wiki.

+
+
+

Note

+

For Reloaded3 theme use reloaded3-slate instead of reloaded-slate.

+
+

Extra

+
+

Info

+

Most documentation pages will also include additional plugins; some which are used in the pages here.
+Here is a sample complete mkdocs.yml you can copy to your project for reference.

+
+

Technical Questions

+

If you have questions/bug reports/etc. feel free to Open an Issue.

+

Happy Documenting ❤️

+ + + + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/Reloaded/Pages/license/index.html b/Reloaded/Pages/license/index.html new file mode 100644 index 0000000..ca5baff --- /dev/null +++ b/Reloaded/Pages/license/index.html @@ -0,0 +1,1192 @@ + + + + + + + + + + + + + + + + + + + + + + + + License - Reloaded Memory Library + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + + + + + +
+
+ + + + + + + + +

The Reloaded Project License

+
+

Most components of the Reloaded are governed by the GPLv3 license.

+
+
+

In some, albeit rare scenarios, certain libraries might be licensed under LGPLv3 instead.

+
+

This is a FAQ meant to clarify the licensing choice and its implications. +Please note, though, that the full license text is the final legal authority.

+

Why was GPL v3 chosen?

+
+

The primary objective is to prevent closed-source, commercial exploitation of the project.

+
+

We want to ensure that the project isn't used within a proprietary environment for +profit-making purposes such as:

+
    +
  • Being sold behind a Patreon paywall.
  • +
  • Being integrated into a closed-source commercial product for sale.
  • +
+
+

The Reloaded Project is a labour of love from unpaid hobbyist volunteers.

+
+

Exploiting that work for profit feels fundamentally unfair.

+

While the GPLv3 license doesn't prohibit commercial use outright, it does prevent commercial +exploitation by requiring that contributions are given back to the open-source community.

+

In that fashion, everyone can benefit from the projects under the Reloaded label.

+

Can I use Reloaded Libraries Commercially?

+

You can as long as the resulting produce is also licensed under GPLv3, and thus open source.

+

Can I use Reloaded Libraries in a closed-source application?

+
+

The license terms do not permit this.

+
+

However, if your software is completely non-commercial, meaning it's neither +sold for profit, funded in development, nor hidden behind a paywall (like Patreon), +we probably just look the other way.

+

This often applies to non-professional programmers, learners, or those +with no intent to exploit the project. We believe in understanding and +leniency for those who might not know better.

+

GPL v3 exists to protect the project and its contributors. If you're not exploiting the project for commercial +gain, you're not hurting us; and we will not enforce the terms of the GPL.

+

If you are interested in obtaining a commercial license, or want an explicit written exemption, +please get in touch with the repository owners.

+ +

Yes, as long as you adhere to the GPLv3 license terms, you're permitted to statically +link Reloaded Libraries into your project, for instance, through the use of NativeAOT or ILMerge.

+

Guidelines for Non-Commercial Use

+

We support and encourage the non-commercial use of Reloaded Libraries. +Non-commercial use generally refers to the usage of our libraries for personal projects, +educational purposes, academic research, or use by non-profit organizations.

+

Personal Projects

+

You're free to use our libraries for projects that you undertake +for your own learning, hobby or personal enjoyment. This includes creating mods for your +favorite games or building your own applications for personal use.

+

Educational Use

+

Teachers and students are welcome to use our libraries as a learning +resource. You can incorporate them into your teaching materials, student projects, coding +bootcamps, workshops, etc.

+

Academic Research

+

Researchers may use our libraries for academic and scholarly research. +We'd appreciate if you cite our work in any publications that result from research involving our libraries.

+

Non-profit Organizations

+

If you're part of a registered non-profit organization, +you can use our libraries in your projects. However, any derivative work that uses our +libraries must also be released under the GPL.

+

Please remember, if your usage of our libraries evolves from non-commercial to commercial, +you must ensure compliance with the terms of the GPL v3 license.

+

Attribution Requirements

+

As Reloaded Project is a labor of love, done purely out of passion and with an aim to contribute +to the broader community, we highly appreciate your support in providing attribution when using +our libraries.

+

While not legally mandatory under GPL v3, it is a simple act that can go a long +way in recognizing the efforts of our contributors and fostering an open and collaborative atmosphere.

+

If you choose to provide attribution (and we hope you do!), here are some guidelines:

+
    +
  • +

    Acknowledge the Use of Reloaded Libraries: Mention that your project uses or is based on Reloaded libraries. + This could be in your project's readme, a credits page on a website, a manual, or within the software itself.

    +
  • +
  • +

    Link to the Project: If possible, provide a link back to the Reloaded Project. + This allows others to explore and potentially benefit from our work.

    +
  • +
+

Remember, attribution is more than just giving credit,,, it's a way of saying thank you 👉👈, fostering reciprocal +respect, and acknowledging the power of collaborative open-source development.

+

We appreciate your support and look forward to seeing what amazing projects you create using Reloaded libraries!

+

Code from MIT/BSD Licensed Projects

+

In some rare instances, code from more permissively licensed projects, such as those under the +MIT or BSD licenses, may be referenced, incorporated, or slightly modified within the Reloaded Project.

+

It's important to us to respect the terms and intentions of these permissive licenses, +which often allow their code to be used in a wide variety of contexts, including in GPL-licensed projects like ours.

+

In these cases, the Reloaded Project is committed to clearly disclosing the usage of such code:

+
    +
  • +

    Method-Level Disclosure: For individual methods or small code snippets, we use appropriate + attribution methods, like programming language attributes. For example, methods borrowed or adapted + from MIT-licensed projects might be marked with a [MITLicense] attribute.

    +
  • +
  • +

    File-Level Disclosure: For larger amounts of code, such as entire files or modules, we'll include + the original license text at the top of the file and clearly indicate which portions of the code originate + from a differently-licensed project.

    +
  • +
  • +

    Project-Level Disclosure: If an entire library or significant portion of a project under a more permissive + license is used, we will include an acknowledgment in a prominent location, such as the readme file or the + project's license documentation.

    +
  • +
+

This approach ensures we honor the contributions of the open source community at large, respect the original +licenses, and maintain transparency with our users about where code originates from.

+

Any files/methods or snippets marked with those attributes may be consumed using their original license terms.

+

i.e. If a method is marked with [MITLicense], you may use it under the terms of the MIT license.

+

Contributing to the Reloaded Project

+

We welcome and appreciate contributions to the Reloaded Project! +By contributing, you agree to share your changes under the same GPLv3 license, +helping to make the project better for everyone.

+ + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/Reloaded/Pages/testing-zone/index.html b/Reloaded/Pages/testing-zone/index.html new file mode 100644 index 0000000..b1ce4f3 --- /dev/null +++ b/Reloaded/Pages/testing-zone/index.html @@ -0,0 +1,1091 @@ + + + + + + + + + + + + + + + + + + + + Testing Zone - Reloaded Memory Library + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Testing Zone

+
+

Info

+

This is a dummy page with various Material MkDocs controls and features scattered throughout for testing.

+
+

Custom Admonitions

+
+

Reloaded Admonition

+

An admonition featuring a Reloaded logo. +My source is in Stylesheets/extra.css as Custom 'reloaded' admonition.

+
+
+

Heart Admonition

+

An admonition featuring a heart; because we want to contribute back to the open source community.
+My source is in Stylesheets/extra.css as Custom 'reloaded heart' admonition.

+
+
+

Nexus Admonition

+

An admonition featuring a Nexus logo. +My source is in Stylesheets/extra.css as Custom 'nexus' admonition.

+
+
+

Heart Admonition

+

An admonition featuring a heart; because we want to contribute back to the open source community.
+My source is in Stylesheets/extra.css as Custom 'nexus heart' admonition.

+
+

Mermaid Diagram

+

Flowchart (Source: Nexus Archive Library):

+
flowchart TD
+    subgraph Block 2
+        BigFile1.bin
+    end
+
+    subgraph Block 1
+        BigFile0.bin
+    end
+
+    subgraph Block 0
+        ModConfig.json -.-> Updates.json 
+        Updates.json -.-> more["... more .json files"]        
+    end
+

Sequence Diagram (Source: Reloaded3 Specification):

+
sequenceDiagram
+
+    % Define Items
+    participant Mod Loader
+    participant Virtual FileSystem (VFS)
+    participant CRI CPK Archive Support
+    participant Persona 5 Royal Support
+    participant Joker Costume
+
+    % Define Actions
+    Mod Loader->>Persona 5 Royal Support: Load Mod
+    Persona 5 Royal Support->>Mod Loader: Request CRI CPK Archive Support API
+    Mod Loader->>Persona 5 Royal Support: Receive CRI CPK Archive Support Instance
+
+    Mod Loader->>Joker Costume: Load Mod
+    Mod Loader-->Persona 5 Royal Support: Notification: 'Loaded Joker Costume'
+    Persona 5 Royal Support->>CRI CPK Archive Support: Add Files from 'Joker Costume' to CPK Archive (via API)
+

State Diagram (Source: Mermaid Docs):

+
stateDiagram-v2
+    [*] --> Still
+    Still --> [*]
+
+    Still --> Moving
+    Moving --> Still
+    Moving --> Crash
+    Crash --> [*]
+

Class Diagram (Arbitrary)

+
classDiagram
+    class Animal
+    `NexusMobile™` <|-- Car
+
+

Note

+

At time of writing, version of Mermaid is a bit outdated here; and other diagrams might not render correctly +(even on unmodified theme); thus certain diagrams have been omitted from here.

+
+

Code Block

+

Snippet from C# version of Sewer's Virtual FileSystem (VFS):

+
/// <summary>
+/// Tries to get files for a specific folder, assuming the input path is already in upper case.
+/// </summary>
+/// <param name="folderPath">The folder to find. Already lowercase.</param>
+/// <param name="value">The returned folder instance.</param>
+/// <returns>True if found, else false.</returns>
+[MethodImpl(MethodImplOptions.AggressiveInlining)]
+public bool TryGetFolderUpper(ReadOnlySpan<char> folderPath, out SpanOfCharDict<TTarget> value)
+{
+    // Must be O(1)
+    value = default!;        
+
+    // Compare equality.
+    // Note to devs: Do not invert branches, we optimise for hot paths here.
+    if (folderPath.StartsWith(Prefix))
+    {
+        // Check for subfolder in branchless way.
+        // In CLR, bool is length 1, so conversion to byte should be safe.
+        // Even suppose it is not; as long as code is little endian; truncating int/4 bytes to byte still results 
+        // in correct answer.
+        var hasSubfolder = Prefix.Length != folderPath.Length;
+        var hasSubfolderByte = Unsafe.As<bool, byte>(ref hasSubfolder);
+        var nextFolder = folderPath.SliceFast(Prefix.Length + hasSubfolderByte);
+
+        return SubfolderToFiles.TryGetValue(nextFolder, out value!);
+    }
+
+    return false;
+}
+
+

Something more number heavy, Fast Inverse Square Root from Quake III Arena (unmodified). +

float Q_rsqrt( float number )
+{
+    long i;
+    float x2, y;
+    const float threehalfs = 1.5F;
+
+    x2 = number * 0.5F;
+    y  = number;
+    i  = * ( long * ) &y;                       // evil floating point bit level hacking
+    i  = 0x5f3759df - ( i >> 1 );               // what the fuck? 
+    y  = * ( float * ) &i;
+    y  = y * ( threehalfs - ( x2 * y * y ) );   // 1st iteration
+//  y  = y * ( threehalfs - ( x2 * y * y ) );   // 2nd iteration, this can be removed
+
+    return y;
+}
+

+

Default Admonitions

+
+

Note

+

Test

+
+
+

Abstract

+

Test

+
+
+

Info

+

Test

+
+
+

Tip

+

Test

+
+
+

Success

+

Test

+
+
+

Question

+

Test

+
+
+

Warning

+

Test

+
+
+

Failure

+

Test

+
+
+

Danger

+

Test

+
+
+

Bug

+

Test

+
+
+

Example

+

Test

+
+
+

Quote

+

Test

+
+

Tables

+ + + + + + + + + + + + + + + + + + + + + +
MethodDescription
GET Fetch resource
PUT Update resource
DELETE Delete resource
+ + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/Reloaded/Readme/index.html b/Reloaded/Readme/index.html new file mode 100644 index 0000000..5be36c1 --- /dev/null +++ b/Reloaded/Readme/index.html @@ -0,0 +1,843 @@ + + + + + + + + + + + + + + + + + + + + Readme - Reloaded Memory Library + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+ +
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/Reloaded/Stylesheets/Montserrat-Bold.ttf b/Reloaded/Stylesheets/Montserrat-Bold.ttf new file mode 100644 index 0000000..efddc83 Binary files /dev/null and b/Reloaded/Stylesheets/Montserrat-Bold.ttf differ diff --git a/Reloaded/Stylesheets/Montserrat-Regular.ttf b/Reloaded/Stylesheets/Montserrat-Regular.ttf new file mode 100644 index 0000000..aa9033a Binary files /dev/null and b/Reloaded/Stylesheets/Montserrat-Regular.ttf differ diff --git a/Reloaded/Stylesheets/Montserrat-SemiBold.ttf b/Reloaded/Stylesheets/Montserrat-SemiBold.ttf new file mode 100644 index 0000000..cbf44db Binary files /dev/null and b/Reloaded/Stylesheets/Montserrat-SemiBold.ttf differ diff --git a/Reloaded/Stylesheets/extra.css b/Reloaded/Stylesheets/extra.css new file mode 100644 index 0000000..b183a12 --- /dev/null +++ b/Reloaded/Stylesheets/extra.css @@ -0,0 +1,597 @@ +/* + Nexus Mods Theme +*/ + +:root { + --md-admonition-icon--nexus: url('../Images/Nexus-Icon-40.png'); + --md-admonition-icon--nexusheart: url('../Images/Nexus-Heart-40.png'); + --md-admonition-icon--reloaded: url('../Images/Reloaded-Icon-40.png'); + --md-admonition-icon--reloadedheart: url('../Images/Reloaded-Heart-40.png'); +} + +/* Slate theme, i.e. dark mode */ + +[data-md-color-scheme="nexus-slate"] { + /* + Default Variables + */ + + /* For reuse later */ + --md-primary-fg-color-rgb: 217, 143, 64; + + /* Primary color shades */ + --md-primary-fg-color: #D98F40; + --md-primary-fg-color--light: #E0A362; + --md-primary-fg-color--dark: #C87B28; + + --md-primary-bg-color: #FFFFFF; + --md-primary-bg-color--light: #FFFFFFB2; + + /* Accent color shades */ + --md-accent-fg-color: #C87B28; + --md-accent-fg-color--transparent: #C87B2810; + + --md-accent-bg-color: #2A2C2B; + --md-accent-bg-color--light: #2A2C2B; + +/* + // Slate's hue in the range [0,360] - change this variable to alter the tone + // of the theme, e.g. to make it more redish or greenish. This is a slate- + // specific variable, but the same approach may be adapted to custom themes. +*/ + --md-hue: 31; + --nexus-background-primary: #101010; + --nexus-background-secondary: #181818; + --nexus-background-tertiary: #222222; + --nexus-background-content-primary: #1C1C1C; + --nexus-background-content-secondary: #2B2D2F; + + --nexus-font-primary: #FFFFFF; /* #FFFFFF */ + --nexus-font-secondary: #AAAAAA; /* #AAAAAA */ + --nexus-font-tertiary: #5A5A5A; /* #5A5A5A */ + + --nexus-font-primary-rgb: 255, 255, 255; /* #FFFFFF */ + --nexus-font-secondary-rgb: 170, 170, 170; /* #AAAAAA */ + --nexus-font-tertiary-rgb: 90, 90, 90; /* #5A5A5A */ + + /* Default color shades */ + --md-default-fg-color: var(--nexus-font-primary); + --md-default-fg-color--light: var(--nexus-font-secondary); + --md-default-fg-color--lighter: var(--nexus-font-tertiary); + --md-default-fg-color--lightest: rgba(var(--nexus-font-primary-rgb), 0.12); + --md-default-bg-color: var(--nexus-background-secondary); + --md-default-bg-color--light: var(--nexus-background-content-primary); + --md-default-bg-color--lighter: var(--nexus-background-tertiary); + --md-default-bg-color--lightest: var(--nexus-background-content-secondary); + + /* Code color shades */ + --md-code-fg-color: hsla(var(--md-hue), 18%, 86%, 1); + --md-code-bg-color: var(--nexus-background-content-secondary); + + /* Code highlighting color shades */ + --md-code-hl-color: #4287ff26; + --md-code-hl-number-color: hsla(219, 74%, 63%, 1); + --md-code-hl-special-color: hsla(340, 83%, 66%, 1); + --md-code-hl-function-color: hsla(219, 57%, 65%, 1); + --md-code-hl-constant-color: hsla(250, 62%, 70%, 1); + --md-code-hl-keyword-color: hsla(var(--md-hue), 66%, 64%, 1); + --md-code-hl-string-color: hsla(150, 58%, 44%, 1); + --md-code-hl-name-color: var(--md-code-fg-color); + --md-code-hl-operator-color: var(--md-default-fg-color--light); + --md-code-hl-punctuation-color: var(--md-default-fg-color--light); + --md-code-hl-comment-color: var(--md-default-fg-color--light); + --md-code-hl-generic-color: var(--md-default-fg-color--light); + --md-code-hl-variable-color: var(--md-default-fg-color--light); + + /* Typeset color shades */ + --md-typeset-color: var(--md-default-fg-color); + + /* Typeset `a` color shades */ + --md-typeset-a-color: var(--md-primary-fg-color); + + /* Typeset `mark` color shades */ + --md-typeset-mark-color: #4287ff4d; + + /* Typeset `kbd` color shades */ + --md-typeset-kbd-color: hsla(var(--md-hue), 15%, 94%, 0.12); + --md-typeset-kbd-accent-color: hsla(var(--md-hue), 15%, 94%, 0.2); + --md-typeset-kbd-border-color: hsla(var(--md-hue), 15%, 14%, 1); + + /* Typeset `table` color shades */ + --md-typeset-table-color: hsla(var(--md-hue), 75%, 95%, 0.12); + --md-typeset-table-color--light: hsla(var(--md-hue), 75%, 95%, 0.035); + + /* Admonition color shades */ + --md-admonition-fg-color: var(--md-default-fg-color); + --md-admonition-bg-color: var(--md-default-bg-color); + + /* Footer color shades */ + --md-footer-bg-color: var(--nexus-background-primary); + --md-footer-bg-color--dark: var(--nexus-background-primary); + + /* Shadow depth 1 */ + --md-shadow-z1: + 0 #{px2rem(4px)} #{px2rem(10px)} hsla(0, 0%, 0%, 0.2), + 0 0 #{px2rem(1px)} hsla(0, 0%, 0%, 0.1); + + /* Shadow depth 2 */ + --md-shadow-z2: + 0 #{px2rem(4px)} #{px2rem(10px)} hsla(0, 0%, 0%, 0.3), + 0 0 #{px2rem(1px)} hsla(0, 0%, 0%, 0.25); + + /* Shadow depth 3 */ + --md-shadow-z3: + 0 #{px2rem(4px)} #{px2rem(10px)} hsla(0, 0%, 0%, 0.4), + 0 0 #{px2rem(1px)} hsla(0, 0%, 0%, 0.35); + + /* Hide images for light mode */ + img[src$="#only-light"], + img[src$="#gh-light-mode-only"] { + display: none; + } + + /* Show images for dark mode */ + img[src$="#only-dark"], + img[src$="#gh-dark-mode-only"] { + display: initial; + } +} + +[data-md-color-scheme="nexus-slate"] .md-header { + background-color: var(--nexus-background-primary); +} + +[data-md-color-scheme="reloaded-slate"] { + /* + Default Variables + */ + + /* For reuse later */ + --md-primary-fg-color-rgb: 182, 99, 99; + + /* Primary color shades */ + --md-primary-fg-color: #793939; + --md-primary-fg-color--light: #B66363; + --md-primary-fg-color--lightest: #d6a8a8; + --md-primary-fg-color--dark: #572929; + + --md-primary-bg-color: #FFFFFF; + --md-primary-bg-color--light: #FFFFFFB2; + + /* Accent color shades */ + --md-accent-fg-color: #793939; + --md-accent-fg-color--transparent: #79393960; + + --md-accent-bg-color: #181818; + --md-accent-bg-color--light: #181818; + + /* + // Slate's hue in the range [0,360] - change this variable to alter the tone + // of the theme, e.g. to make it more redish or greenish. This is a slate- + // specific variable, but the same approach may be adapted to custom themes. + */ + --md-hue: 0; + --nexus-background-primary: #101010; + --nexus-background-secondary: #181818; + --nexus-background-tertiary: #222222; + --nexus-background-content-primary: #1C1C1C; + --nexus-background-content-secondary: #2B2D2F; + + --nexus-font-primary: #FFFFFF; /* #FFFFFF */ + --nexus-font-secondary: #AAAAAA; /* #AAAAAA */ + --nexus-font-tertiary: #5A5A5A; /* #5A5A5A */ + + --nexus-font-primary-rgb: 255, 255, 255; /* #FFFFFF */ + --nexus-font-secondary-rgb: 170, 170, 170; /* #AAAAAA */ + --nexus-font-tertiary-rgb: 90, 90, 90; /* #5A5A5A */ + + /* Default color shades */ + --md-default-fg-color: var(--nexus-font-primary); + --md-default-fg-color--light: var(--nexus-font-secondary); + --md-default-fg-color--lighter: var(--nexus-font-tertiary); + --md-default-fg-color--lightest: rgba(var(--nexus-font-primary-rgb), 0.04); + --md-default-bg-color: var(--nexus-background-secondary); + --md-default-bg-color--light: var(--nexus-background-content-primary); + --md-default-bg-color--lighter: var(--nexus-background-tertiary); + --md-default-bg-color--lightest: var(--nexus-background-content-secondary); + + /* Code color shades */ + --md-code-fg-color: hsla(var(--md-hue), 18%, 86%, 1); + --md-code-bg-color: var(--nexus-background-content-secondary); + + /* Code highlighting color shades */ + --md-code-hl-color: #4287ff26; + --md-code-hl-number-color: hsla(219, 74%, 63%, 1); + --md-code-hl-special-color: hsla(340, 83%, 66%, 1); + --md-code-hl-function-color: hsla(219, 57%, 65%, 1); + --md-code-hl-constant-color: hsla(250, 62%, 70%, 1); + --md-code-hl-keyword-color: hsla(var(--md-hue), 66%, 64%, 1); + --md-code-hl-string-color: hsla(150, 58%, 44%, 1); + --md-code-hl-name-color: var(--md-code-fg-color); + --md-code-hl-operator-color: var(--md-default-fg-color--light); + --md-code-hl-punctuation-color: var(--md-default-fg-color--light); + --md-code-hl-comment-color: var(--md-default-fg-color--light); + --md-code-hl-generic-color: var(--md-default-fg-color--light); + --md-code-hl-variable-color: var(--md-default-fg-color--light); + + /* Typeset color shades */ + --md-typeset-color: var(--md-default-fg-color); + + /* Typeset `a` color shades */ + --md-typeset-a-color: var(--md-primary-fg-color--lightest); + + /* Typeset `mark` color shades */ + --md-typeset-mark-color: #4287ff4d; + + /* Typeset `kbd` color shades */ + --md-typeset-kbd-color: hsla(var(--md-hue), 15%, 94%, 0.12); + --md-typeset-kbd-accent-color: hsla(var(--md-hue), 15%, 94%, 0.2); + --md-typeset-kbd-border-color: hsla(var(--md-hue), 15%, 14%, 1); + + /* Typeset `table` color shades */ + --md-typeset-table-color: hsla(var(--md-hue), 75%, 95%, 0.12); + --md-typeset-table-color--light: hsla(var(--md-hue), 75%, 95%, 0.035); + + /* Admonition color shades */ + --md-admonition-fg-color: var(--md-default-fg-color); + --md-admonition-bg-color: var(--md-default-bg-color); + + /* Footer color shades */ + --md-footer-bg-color: var(--nexus-background-primary); + --md-footer-bg-color--dark: var(--nexus-background-primary); + + /* Shadow depth 1 */ + --md-shadow-z1: + 0 #{px2rem(4px)} #{px2rem(10px)} hsla(0, 0%, 0%, 0.2), + 0 0 #{px2rem(1px)} hsla(0, 0%, 0%, 0.1); + + /* Shadow depth 2 */ + --md-shadow-z2: + 0 #{px2rem(4px)} #{px2rem(10px)} hsla(0, 0%, 0%, 0.3), + 0 0 #{px2rem(1px)} hsla(0, 0%, 0%, 0.25); + + /* Shadow depth 3 */ + --md-shadow-z3: + 0 #{px2rem(4px)} #{px2rem(10px)} hsla(0, 0%, 0%, 0.4), + 0 0 #{px2rem(1px)} hsla(0, 0%, 0%, 0.35); + + /* Hide images for light mode */ + img[src$="#only-light"], + img[src$="#gh-light-mode-only"] { + display: none; + } + + /* Show images for dark mode */ + img[src$="#only-dark"], + img[src$="#gh-dark-mode-only"] { + display: initial; + } +} + +[data-md-color-scheme="reloaded-slate"] .md-typeset a:hover { + color: var(--md-primary-fg-color--light); +} + +[data-md-color-scheme="reloaded-slate"] .md-nav--primary .md-nav__item--active>.md-nav__link:hover { + color: var(--md-primary-fg-color--light); +} + +[data-md-color-scheme="reloaded-slate"] .md-nav__link:hover { + color: var(--md-primary-fg-color--light); +} + + +[data-md-color-scheme="reloaded3-slate"] { + /* + Default Variables + */ + + /* For reuse later */ + --md-primary-fg-color-rgb: 63, 153, 217; + + /* Primary color shades */ + --md-primary-fg-color: #fa7774; + --md-primary-fg-color--light: #fc918b; + --md-primary-fg-color--dark: #e96060; + --md-primary-fg-color--darker: #d74f52; + --md-primary-fg-color--darkest: #c53e44; + + --md-primary-bg-color: #FFFFFF; + --md-primary-bg-color--light: #FFFFFFB2; + + /* Accent color shades */ + --md-accent-fg-color: #e96060; + --md-accent-fg-color--transparent: #e9606030; + + --md-accent-bg-color: #2A2C2B; + --md-accent-bg-color--light: #2A2C2B; + + /* + // Slate's hue in the range [0,360] - change this variable to alter the tone + // of the theme, e.g. to make it more redish or greenish. This is a slate- + // specific variable, but the same approach may be adapted to custom themes. + */ + --md-hue: 1; + --nexus-background-primary: #101010; + --nexus-background-secondary: #181818; + --nexus-background-tertiary: #222222; + --nexus-background-content-primary: #1C1C1C; + --nexus-background-content-secondary: #2B2D2F; + + --nexus-font-primary: #FFFFFF; /* #FFFFFF */ + --nexus-font-secondary: #AAAAAA; /* #AAAAAA */ + --nexus-font-tertiary: #5A5A5A; /* #5A5A5A */ + + --nexus-font-primary-rgb: 255, 255, 255; /* #FFFFFF */ + --nexus-font-secondary-rgb: 170, 170, 170; /* #AAAAAA */ + --nexus-font-tertiary-rgb: 90, 90, 90; /* #5A5A5A */ + + /* Default color shades */ + --md-default-fg-color: var(--nexus-font-primary); + --md-default-fg-color--light: var(--nexus-font-secondary); + --md-default-fg-color--lighter: var(--nexus-font-tertiary); + --md-default-fg-color--lightest: rgba(var(--nexus-font-primary-rgb), 0.12); + --md-default-bg-color: var(--nexus-background-secondary); + --md-default-bg-color--light: var(--nexus-background-content-primary); + --md-default-bg-color--lighter: var(--nexus-background-tertiary); + --md-default-bg-color--lightest: var(--nexus-background-content-secondary); + + /* Code color shades */ + --md-code-fg-color: hsla(var(--md-hue), 18%, 86%, 1); + --md-code-bg-color: var(--nexus-background-content-secondary); + + /* Code highlighting color shades */ + --md-code-hl-color: #4287ff26; + --md-code-hl-number-color: hsla(219, 74%, 63%, 1); + --md-code-hl-special-color: hsla(340, 83%, 66%, 1); + --md-code-hl-function-color: hsla(219, 57%, 65%, 1); + --md-code-hl-constant-color: hsla(250, 62%, 70%, 1); + --md-code-hl-keyword-color: hsla(var(--md-hue), 66%, 64%, 1); + --md-code-hl-string-color: hsla(150, 58%, 44%, 1); + --md-code-hl-name-color: var(--md-code-fg-color); + --md-code-hl-operator-color: var(--md-default-fg-color--light); + --md-code-hl-punctuation-color: var(--md-default-fg-color--light); + --md-code-hl-comment-color: var(--md-default-fg-color--light); + --md-code-hl-generic-color: var(--md-default-fg-color--light); + --md-code-hl-variable-color: var(--md-default-fg-color--light); + + /* Typeset color shades */ + --md-typeset-color: var(--md-default-fg-color); + + /* Typeset `a` color shades */ + --md-typeset-a-color: var(--md-primary-fg-color); + + /* Typeset `mark` color shades */ + --md-typeset-mark-color: #4287ff4d; + + /* Typeset `kbd` color shades */ + --md-typeset-kbd-color: hsla(var(--md-hue), 15%, 94%, 0.12); + --md-typeset-kbd-accent-color: hsla(var(--md-hue), 15%, 94%, 0.2); + --md-typeset-kbd-border-color: hsla(var(--md-hue), 15%, 14%, 1); + + /* Typeset `table` color shades */ + --md-typeset-table-color: hsla(var(--md-hue), 75%, 95%, 0.12); + --md-typeset-table-color--light: hsla(var(--md-hue), 75%, 95%, 0.035); + + /* Admonition color shades */ + --md-admonition-fg-color: var(--md-default-fg-color); + --md-admonition-bg-color: var(--md-default-bg-color); + + /* Footer color shades */ + --md-footer-bg-color: var(--nexus-background-primary); + --md-footer-bg-color--dark: var(--nexus-background-primary); + + /* Shadow depth 1 */ + --md-shadow-z1: + 0 #{px2rem(4px)} #{px2rem(10px)} hsla(0, 0%, 0%, 0.2), + 0 0 #{px2rem(1px)} hsla(0, 0%, 0%, 0.1); + + /* Shadow depth 2 */ + --md-shadow-z2: + 0 #{px2rem(4px)} #{px2rem(10px)} hsla(0, 0%, 0%, 0.3), + 0 0 #{px2rem(1px)} hsla(0, 0%, 0%, 0.25); + + /* Shadow depth 3 */ + --md-shadow-z3: + 0 #{px2rem(4px)} #{px2rem(10px)} hsla(0, 0%, 0%, 0.4), + 0 0 #{px2rem(1px)} hsla(0, 0%, 0%, 0.35); + + /* Hide images for light mode */ + img[src$="#only-light"], + img[src$="#gh-light-mode-only"] { + display: none; + } + + /* Show images for dark mode */ + img[src$="#only-dark"], + img[src$="#gh-dark-mode-only"] { + display: initial; + } +} + +[data-md-color-scheme="reloaded3-slate"] .md-header { + background-color: var(--md-primary-fg-color--darker); +} + +@media screen and (max-width: 76.1875em) { + /* Title in Drawer */ + [data-md-color-scheme="reloaded3-slate"] .md-nav--primary .md-nav__title[for=__drawer] { + background-color: var(--md-primary-fg-color--darker); + color: var(--md-primary-bg-color); + font-weight: 700; + } +} + +[data-md-color-scheme="reloaded3-slate"] .md-nav__source { + background-color: var(--md-primary-fg-color--darkest); + color: var(--md-primary-bg-color); +} + +.md-nav__title { + color: var(--md-default-fg-color); +} + +.md-nav__link { + color: var(--md-default-fg-color--light); +} + +/* Custom 'nexus' admonition */ +.md-typeset .admonition.nexus, +.md-typeset details.nexus { + border-color: var(--md-primary-fg-color); +} +.md-typeset .nexus > .admonition-title, +.md-typeset .nexus > summary { + background-color: rgba(var(--md-primary-fg-color-rgb), 0.1); +} +.md-typeset .nexus > .admonition-title::before, +.md-typeset .nexus > summary::before { + background-color: unset; + -webkit-mask-image: unset; + background-image: var(--md-admonition-icon--nexus); + background-size: contain; + background-repeat: no-repeat; + background-position: center; +} + +/* Custom 'nexus heart' admonition */ +.md-typeset .admonition.nexusheart, +.md-typeset details.nexusheart { + border-color: var(--md-primary-fg-color); +} +.md-typeset .nexusheart > .admonition-title, +.md-typeset .nexusheart > summary { + background-color: rgba(var(--md-primary-fg-color-rgb), 0.1); +} +.md-typeset .nexusheart > .admonition-title::before, +.md-typeset .nexusheart > summary::before { + background-color: unset; + -webkit-mask-image: unset; + background-image: var(--md-admonition-icon--nexusheart); + background-size: contain; + background-repeat: no-repeat; + background-position: center; +} + +/* Custom 'reloaded' admonition */ + +.md-typeset .admonition.reloaded, +.md-typeset details.reloaded { + border-color: var(--md-primary-fg-color); +} +.md-typeset .reloaded > .admonition-title, +.md-typeset .reloaded > summary { + background-color: rgba(var(--md-primary-fg-color-rgb), 0.1); +} +.md-typeset .reloaded > .admonition-title::before, +.md-typeset .reloaded > summary::before { + background-color: unset; + -webkit-mask-image: unset; + background-image: var(--md-admonition-icon--reloaded); + background-size: contain; + background-repeat: no-repeat; + background-position: center; +} + +/* Custom 'nexus heart' admonition */ +.md-typeset .admonition.reloadedheart, +.md-typeset details.reloadedheart { + border-color: var(--md-primary-fg-color); +} +.md-typeset .reloadedheart > .admonition-title, +.md-typeset .reloadedheart > summary { + background-color: rgba(var(--md-primary-fg-color-rgb), 0.1); +} +.md-typeset .reloadedheart > .admonition-title::before, +.md-typeset .reloadedheart > summary::before { + background-color: unset; + -webkit-mask-image: unset; + background-image: var(--md-admonition-icon--reloadedheart); + background-size: contain; + background-repeat: no-repeat; + background-position: center; +} + +/* Add Title Font */ +@font-face { + font-family: "Montserrat"; + src: url("./Montserrat-Regular.ttf") format("truetype"); + font-weight: normal; +} + +@font-face { + font-family: "Montserrat"; + src: url("./Montserrat-SemiBold.ttf") format("truetype"); + font-weight: 600; +} + +@font-face { + font-family: "Montserrat"; + src: url("./Montserrat-Bold.ttf") format("truetype"); + font-weight: bold; +} + +/* Headers */ +[data-md-color-scheme="nexus-slate"] .md-typeset h1 { + color: var(--md-default-fg-color); + font-family: "Montserrat",Roboto; + font-weight: 600; +} + +[data-md-color-scheme="nexus-slate"] .md-typeset h2 { + color: var(--md-default-fg-color); + font-family: "Montserrat",Roboto; + font-weight: 600; +} + +[data-md-color-scheme="nexus-slate"] .md-typeset h3 { + color: var(--md-default-fg-color); + font-family: "Montserrat",Roboto; + font-weight: 600; +} + +[data-md-color-scheme="nexus-slate"] .md-typeset h4 { + color: var(--md-default-fg-color); + font-family: "Montserrat",Roboto; + font-weight: 600; +} + +[data-md-color-scheme="nexus-slate"] .md-typeset h5 { + color: var(--md-default-fg-color); + font-family: "Montserrat",Roboto; + font-weight: 600; +} + +[data-md-color-scheme="reloaded-slate"] .md-typeset h1 { + color: var(--md-default-fg-color); +} + +[data-md-color-scheme="reloaded3-slate"] .md-typeset h1 { + color: var(--md-default-fg-color); + font-family: "Montserrat",Roboto; + font-weight: 600; +} + +[data-md-color-scheme="reloaded3-slate"] .md-typeset h2 { + color: var(--md-default-fg-color); + font-family: "Montserrat",Roboto; + font-weight: 600; +} + +[data-md-color-scheme="reloaded3-slate"] .md-typeset h3 { + color: var(--md-default-fg-color); + font-family: "Montserrat",Roboto; + font-weight: 600; +} + +[data-md-color-scheme="reloaded3-slate"] .md-typeset h4 { + color: var(--md-default-fg-color); + font-family: "Montserrat",Roboto; + font-weight: 600; +} + +[data-md-color-scheme="reloaded3-slate"] .md-typeset h5 { + color: var(--md-default-fg-color); + font-family: "Montserrat",Roboto; + font-weight: 600; +} \ No newline at end of file diff --git a/Reloaded/docs/Images/Contribute/ForkTheRepo.png b/Reloaded/docs/Images/Contribute/ForkTheRepo.png new file mode 100644 index 0000000..db1f529 Binary files /dev/null and b/Reloaded/docs/Images/Contribute/ForkTheRepo.png differ diff --git a/Reloaded/docs/Images/Contribute/GitHubDesktop.png b/Reloaded/docs/Images/Contribute/GitHubDesktop.png new file mode 100644 index 0000000..75b8f71 Binary files /dev/null and b/Reloaded/docs/Images/Contribute/GitHubDesktop.png differ diff --git a/Reloaded/docs/Images/Contribute/LocalRun.png b/Reloaded/docs/Images/Contribute/LocalRun.png new file mode 100644 index 0000000..d15f556 Binary files /dev/null and b/Reloaded/docs/Images/Contribute/LocalRun.png differ diff --git a/Reloaded/docs/Images/Contribute/OpenPR.png b/Reloaded/docs/Images/Contribute/OpenPR.png new file mode 100644 index 0000000..e2d1aba Binary files /dev/null and b/Reloaded/docs/Images/Contribute/OpenPR.png differ diff --git a/Reloaded/docs/Images/Contribute/OpenPullRequest.png b/Reloaded/docs/Images/Contribute/OpenPullRequest.png new file mode 100644 index 0000000..e2d1aba Binary files /dev/null and b/Reloaded/docs/Images/Contribute/OpenPullRequest.png differ diff --git a/Reloaded/docs/Images/Contribute/Rider.png b/Reloaded/docs/Images/Contribute/Rider.png new file mode 100644 index 0000000..27f380c Binary files /dev/null and b/Reloaded/docs/Images/Contribute/Rider.png differ diff --git a/Reloaded/docs/Images/Nexus-Heart-40.png b/Reloaded/docs/Images/Nexus-Heart-40.png new file mode 100644 index 0000000..3337565 Binary files /dev/null and b/Reloaded/docs/Images/Nexus-Heart-40.png differ diff --git a/Reloaded/docs/Images/Nexus-Heart.png b/Reloaded/docs/Images/Nexus-Heart.png new file mode 100644 index 0000000..43f7a26 Binary files /dev/null and b/Reloaded/docs/Images/Nexus-Heart.png differ diff --git a/Reloaded/docs/Images/Nexus-Heart.psd b/Reloaded/docs/Images/Nexus-Heart.psd new file mode 100644 index 0000000..473c865 Binary files /dev/null and b/Reloaded/docs/Images/Nexus-Heart.psd differ diff --git a/Reloaded/docs/Images/Nexus-Icon-40.png b/Reloaded/docs/Images/Nexus-Icon-40.png new file mode 100644 index 0000000..8781822 Binary files /dev/null and b/Reloaded/docs/Images/Nexus-Icon-40.png differ diff --git a/Reloaded/docs/Images/Nexus-Icon.png b/Reloaded/docs/Images/Nexus-Icon.png new file mode 100644 index 0000000..3e611b4 Binary files /dev/null and b/Reloaded/docs/Images/Nexus-Icon.png differ diff --git a/Reloaded/docs/Images/Reloaded-Heart-40.png b/Reloaded/docs/Images/Reloaded-Heart-40.png new file mode 100644 index 0000000..6fdf9da Binary files /dev/null and b/Reloaded/docs/Images/Reloaded-Heart-40.png differ diff --git a/Reloaded/docs/Images/Reloaded-Heart.png b/Reloaded/docs/Images/Reloaded-Heart.png new file mode 100644 index 0000000..0ed75b3 Binary files /dev/null and b/Reloaded/docs/Images/Reloaded-Heart.png differ diff --git a/Reloaded/docs/Images/Reloaded-Icon-40.png b/Reloaded/docs/Images/Reloaded-Icon-40.png new file mode 100644 index 0000000..9a43d61 Binary files /dev/null and b/Reloaded/docs/Images/Reloaded-Icon-40.png differ diff --git a/Reloaded/docs/Images/Reloaded-Icon.png b/Reloaded/docs/Images/Reloaded-Icon.png new file mode 100644 index 0000000..ae0d6d2 Binary files /dev/null and b/Reloaded/docs/Images/Reloaded-Icon.png differ diff --git a/Reloaded/docs/Images/Reloaded-Templates.7z b/Reloaded/docs/Images/Reloaded-Templates.7z new file mode 100644 index 0000000..371a063 Binary files /dev/null and b/Reloaded/docs/Images/Reloaded-Templates.7z differ diff --git a/Reloaded/docs/Pages/contributing/index.html b/Reloaded/docs/Pages/contributing/index.html new file mode 100644 index 0000000..c9a5510 --- /dev/null +++ b/Reloaded/docs/Pages/contributing/index.html @@ -0,0 +1,946 @@ + + + + + + + + + + + + + + + + + + + + Contributing to the Wiki: Locally - Reloaded Memory Library + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Contributing to the Wiki: Locally

+
+

Info

+

This page shows you how to contribute to any documentation page or wiki +based on this template.

+
+
+

Note

+

This theme is forked from my theme for Nexus Docs; +and this page is synced with that.

+
+

Tutorial

+
+

Note

+

If you are editing the repository with the theme itself on Windows, it might be a good idea to run +git config core.symlinks true first to allow git to create symlinks on clone.

+
+

You should learn the basics of git, an easy way is to give GitHub Desktop (Tutorial) a go.
+It's only 15 minutes 😀.

+
    +
  1. Create a GitHub account.
  2. +
  3. +

    Fork this repository:

    +

    Image

    +

    This will create a copy of the repository on your own user account, which you will be able to edit.

    +
  4. +
  5. +

    Clone this repository.

    +

    For example, using GitHub Desktop: +Image

    +
  6. +
  7. +

    Make changes inside the docs folder.

    +

    Image

    +

    Consider using a Markdown Cheat Sheet if you are new to markdown.

    +

    I recommend using a markdown editor such as Typora.
    +Personally I just work from inside Rider.

    +
  8. +
  9. +

    Commit the changes and push to GitHub.

    +
  10. +
  11. +

    Open a Pull Request.

    +

    Image

    +

    Opening a Pull Request will allow us to review your changes before adding them with the main official page. If everything's good, we'll hit the merge button and add your changes to the official repository.

    +
  12. +
+

Website Live Preview

+

If you are working on the wiki locally, you can generate a live preview the full website. +Here's a quick guide of how you could do it from your command prompt (cmd).

+
    +
  1. +

    Install Python 3

    +

    If you have winget installed, or Windows 11, you can do this from the command prompt. +

    winget install Python.Python.3
    +

    +

    Otherwise download Python 3 from the official website or package manager.

    +
  2. +
  3. +

    Install Material for MkDocs and Plugins (Python package) +

    # Restart your command prompt before running this command.
    +pip install mkdocs-material
    +pip install mkdocs-redirects
    +

    +
  4. +
  5. +

    Open a command prompt in the folder containing mkdocs.yml. and run the site locally. +

    # Move to project folder.
    +cd <Replace this with full path to folder containing `mkdocs.yml`>
    +mkdocs serve
    +

    +

    Image

    +

    Copy the address to your web browser and enjoy the live preview; any changes you save will be shown instantly.

    +
  6. +
+ + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/Reloaded/docs/Pages/index.html b/Reloaded/docs/Pages/index.html new file mode 100644 index 0000000..e069f4c --- /dev/null +++ b/Reloaded/docs/Pages/index.html @@ -0,0 +1,1020 @@ + + + + + + + + + + + + + + + + + + + + Index - Reloaded Memory Library + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + + + +
+
+
+ + + + +
+
+
+ + + + + + + + + +
+
+ + + + + + + + +

Index

+ +
+

The Reloaded MkDocs Theme

+ +

+ A Theme for MkDocs Material. +
+ That resembles the look of Reloaded. +
+ +

About

+

This it the NexusMods theme for Material-MkDocs, inspired by the look of Reloaded-II.

+

The overall wiki theme should look fairly close to the actual launcher appearance.

+

Setup From Scratch

+
    +
  • Add this repository as submodule to docs/Reloaded.
  • +
  • Save the following configuration as mkdocs.yml in your repository root.
  • +
+
site_name: Reloaded MkDocs Theme
+site_url: https://github.com/Reloaded-Project/Reloaded.MkDocsMaterial.Themes.R2
+
+repo_name: Reloaded-Project/Reloaded.MkDocsMaterial.Themes.R2
+repo_url: https://github.com/Reloaded-Project/Reloaded.MkDocsMaterial.Themes.R2
+
+extra:
+  social:
+    - icon: fontawesome/brands/github
+      link: https://github.com/Reloaded-Project
+    - icon: fontawesome/brands/twitter
+      link: https://twitter.com/thesewer56?lang=en-GB
+
+extra_css:
+  - Reloaded/Stylesheets/extra.css
+
+markdown_extensions:
+  - admonition
+  - tables
+  - pymdownx.details
+  - pymdownx.highlight
+  - pymdownx.superfences:
+      custom_fences:
+        - name: mermaid
+          class: mermaid
+          format: !!python/name:pymdownx.superfences.fence_code_format
+  - pymdownx.tasklist
+  - def_list
+  - meta
+  - md_in_html
+  - attr_list
+  - footnotes
+  - pymdownx.tabbed:
+      alternate_style: true
+  - pymdownx.emoji:
+      emoji_index: !!python/name:materialx.emoji.twemoji
+      emoji_generator: !!python/name:materialx.emoji.to_svg
+
+theme:
+  name: material
+  palette:
+    scheme: reloaded-slate
+  features:
+    - navigation.instant
+
+plugins:
+  - search
+
+nav:
+  - Home: index.md
+
+
    +
  • Add a GitHub Actions workload in .github/workflows/DeployMkDocs.yml.
  • +
+
name: DeployMkDocs
+
+# Controls when the action will run. 
+on:
+  # Triggers the workflow on push on the master branch
+  push:
+    branches: [ main ]
+
+  # Allows you to run this workflow manually from the Actions tab
+  workflow_dispatch:
+
+# A workflow run is made up of one or more jobs that can run sequentially or in parallel
+jobs:
+  # This workflow contains a single job called "build"
+  build:
+    # The type of runner that the job will run on
+    runs-on: ubuntu-latest
+
+    # Steps represent a sequence of tasks that will be executed as part of the job
+    steps:
+
+      # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
+      - name: Checkout Branch
+        uses: actions/checkout@v2
+        with:
+          submodules: recursive
+
+      # Deploy MkDocs
+      - name: Deploy MkDocs
+        # You may pin to the exact commit or the version.
+        # uses: mhausenblas/mkdocs-deploy-gh-pages@66340182cb2a1a63f8a3783e3e2146b7d151a0bb
+        uses: mhausenblas/mkdocs-deploy-gh-pages@master
+        env:
+          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+          REQUIREMENTS: ./docs/requirements.txt
+
+
    +
  • Push to GitHub, this should produce a GitHub Pages site.
  • +
  • Go to Settings -> Pages in your repo and select gh-pages branch to enable GitHub pages.
  • +
+

Your page should then be live.

+
+

Tip

+

Refer to Contributing for instructions on how to locally edit and modify the wiki.

+
+
+

Note

+

For Reloaded3 theme use reloaded3-slate instead of reloaded-slate.

+
+

Extra

+
+

Info

+

Most documentation pages will also include additional plugins; some which are used in the pages here.
+Here is a sample complete mkdocs.yml you can copy to your project for reference.

+
+

Technical Questions

+

If you have questions/bug reports/etc. feel free to Open an Issue.

+

Happy Documenting ❤️

+ + + + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/Reloaded/docs/Pages/license/index.html b/Reloaded/docs/Pages/license/index.html new file mode 100644 index 0000000..9753259 --- /dev/null +++ b/Reloaded/docs/Pages/license/index.html @@ -0,0 +1,1064 @@ + + + + + + + + + + + + + + + + + + + + The Reloaded Project License - Reloaded Memory Library + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + + + + + +
+
+ + + + + + + + +

The Reloaded Project License

+
+

Most components of the Reloaded are governed by the GPLv3 license.

+
+
+

In some, albeit rare scenarios, certain libraries might be licensed under LGPLv3 instead.

+
+

This is a FAQ meant to clarify the licensing choice and its implications. +Please note, though, that the full license text is the final legal authority.

+

Why was GPL v3 chosen?

+
+

The primary objective is to prevent closed-source, commercial exploitation of the project.

+
+

We want to ensure that the project isn't used within a proprietary environment for +profit-making purposes such as:

+
    +
  • Being sold behind a Patreon paywall.
  • +
  • Being integrated into a closed-source commercial product for sale.
  • +
+
+

The Reloaded Project is a labour of love from unpaid hobbyist volunteers.

+
+

Exploiting that work for profit feels fundamentally unfair.

+

While the GPLv3 license doesn't prohibit commercial use outright, it does prevent commercial +exploitation by requiring that contributions are given back to the open-source community.

+

In that fashion, everyone can benefit from the projects under the Reloaded label.

+

Can I use Reloaded Libraries Commercially?

+

You can as long as the resulting produce is also licensed under GPLv3, and thus open source.

+

Can I use Reloaded Libraries in a closed-source application?

+
+

The license terms do not permit this.

+
+

However, if your software is completely non-commercial, meaning it's neither +sold for profit, funded in development, nor hidden behind a paywall (like Patreon), +we probably just look the other way.

+

This often applies to non-professional programmers, learners, or those +with no intent to exploit the project. We believe in understanding and +leniency for those who might not know better.

+

GPL v3 exists to protect the project and its contributors. If you're not exploiting the project for commercial +gain, you're not hurting us; and we will not enforce the terms of the GPL.

+

If you are interested in obtaining a commercial license, or want an explicit written exemption, +please get in touch with the repository owners.

+ +

Yes, as long as you adhere to the GPLv3 license terms, you're permitted to statically +link Reloaded Libraries into your project, for instance, through the use of NativeAOT or ILMerge.

+

Guidelines for Non-Commercial Use

+

We support and encourage the non-commercial use of Reloaded Libraries. +Non-commercial use generally refers to the usage of our libraries for personal projects, +educational purposes, academic research, or use by non-profit organizations.

+

Personal Projects

+

You're free to use our libraries for projects that you undertake +for your own learning, hobby or personal enjoyment. This includes creating mods for your +favorite games or building your own applications for personal use.

+

Educational Use

+

Teachers and students are welcome to use our libraries as a learning +resource. You can incorporate them into your teaching materials, student projects, coding +bootcamps, workshops, etc.

+

Academic Research

+

Researchers may use our libraries for academic and scholarly research. +We'd appreciate if you cite our work in any publications that result from research involving our libraries.

+

Non-profit Organizations

+

If you're part of a registered non-profit organization, +you can use our libraries in your projects. However, any derivative work that uses our +libraries must also be released under the GPL.

+

Please remember, if your usage of our libraries evolves from non-commercial to commercial, +you must ensure compliance with the terms of the GPL v3 license.

+

Attribution Requirements

+

As Reloaded Project is a labor of love, done purely out of passion and with an aim to contribute +to the broader community, we highly appreciate your support in providing attribution when using +our libraries.

+

While not legally mandatory under GPL v3, it is a simple act that can go a long +way in recognizing the efforts of our contributors and fostering an open and collaborative atmosphere.

+

If you choose to provide attribution (and we hope you do!), here are some guidelines:

+
    +
  • +

    Acknowledge the Use of Reloaded Libraries: Mention that your project uses or is based on Reloaded libraries. + This could be in your project's readme, a credits page on a website, a manual, or within the software itself.

    +
  • +
  • +

    Link to the Project: If possible, provide a link back to the Reloaded Project. + This allows others to explore and potentially benefit from our work.

    +
  • +
+

Remember, attribution is more than just giving credit,,, it's a way of saying thank you 👉👈, fostering reciprocal +respect, and acknowledging the power of collaborative open-source development.

+

We appreciate your support and look forward to seeing what amazing projects you create using Reloaded libraries!

+

Code from MIT/BSD Licensed Projects

+

In some rare instances, code from more permissively licensed projects, such as those under the +MIT or BSD licenses, may be referenced, incorporated, or slightly modified within the Reloaded Project.

+

It's important to us to respect the terms and intentions of these permissive licenses, +which often allow their code to be used in a wide variety of contexts, including in GPL-licensed projects like ours.

+

In these cases, the Reloaded Project is committed to clearly disclosing the usage of such code:

+
    +
  • +

    Method-Level Disclosure: For individual methods or small code snippets, we use appropriate + attribution methods, like programming language attributes. For example, methods borrowed or adapted + from MIT-licensed projects might be marked with a [MITLicense] attribute.

    +
  • +
  • +

    File-Level Disclosure: For larger amounts of code, such as entire files or modules, we'll include + the original license text at the top of the file and clearly indicate which portions of the code originate + from a differently-licensed project.

    +
  • +
  • +

    Project-Level Disclosure: If an entire library or significant portion of a project under a more permissive + license is used, we will include an acknowledgment in a prominent location, such as the readme file or the + project's license documentation.

    +
  • +
+

This approach ensures we honor the contributions of the open source community at large, respect the original +licenses, and maintain transparency with our users about where code originates from.

+

Any files/methods or snippets marked with those attributes may be consumed using their original license terms.

+

i.e. If a method is marked with [MITLicense], you may use it under the terms of the MIT license.

+

Contributing to the Reloaded Project

+

We welcome and appreciate contributions to the Reloaded Project! +By contributing, you agree to share your changes under the same GPLv3 license, +helping to make the project better for everyone.

+ + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/Reloaded/docs/Pages/testing-zone/index.html b/Reloaded/docs/Pages/testing-zone/index.html new file mode 100644 index 0000000..15beae7 --- /dev/null +++ b/Reloaded/docs/Pages/testing-zone/index.html @@ -0,0 +1,1091 @@ + + + + + + + + + + + + + + + + + + + + Testing Zone - Reloaded Memory Library + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Testing Zone

+
+

Info

+

This is a dummy page with various Material MkDocs controls and features scattered throughout for testing.

+
+

Custom Admonitions

+
+

Reloaded Admonition

+

An admonition featuring a Reloaded logo. +My source is in Stylesheets/extra.css as Custom 'reloaded' admonition.

+
+
+

Heart Admonition

+

An admonition featuring a heart; because we want to contribute back to the open source community.
+My source is in Stylesheets/extra.css as Custom 'reloaded heart' admonition.

+
+
+

Nexus Admonition

+

An admonition featuring a Nexus logo. +My source is in Stylesheets/extra.css as Custom 'nexus' admonition.

+
+
+

Heart Admonition

+

An admonition featuring a heart; because we want to contribute back to the open source community.
+My source is in Stylesheets/extra.css as Custom 'nexus heart' admonition.

+
+

Mermaid Diagram

+

Flowchart (Source: Nexus Archive Library):

+
flowchart TD
+    subgraph Block 2
+        BigFile1.bin
+    end
+
+    subgraph Block 1
+        BigFile0.bin
+    end
+
+    subgraph Block 0
+        ModConfig.json -.-> Updates.json 
+        Updates.json -.-> more["... more .json files"]        
+    end
+

Sequence Diagram (Source: Reloaded3 Specification):

+
sequenceDiagram
+
+    % Define Items
+    participant Mod Loader
+    participant Virtual FileSystem (VFS)
+    participant CRI CPK Archive Support
+    participant Persona 5 Royal Support
+    participant Joker Costume
+
+    % Define Actions
+    Mod Loader->>Persona 5 Royal Support: Load Mod
+    Persona 5 Royal Support->>Mod Loader: Request CRI CPK Archive Support API
+    Mod Loader->>Persona 5 Royal Support: Receive CRI CPK Archive Support Instance
+
+    Mod Loader->>Joker Costume: Load Mod
+    Mod Loader-->Persona 5 Royal Support: Notification: 'Loaded Joker Costume'
+    Persona 5 Royal Support->>CRI CPK Archive Support: Add Files from 'Joker Costume' to CPK Archive (via API)
+

State Diagram (Source: Mermaid Docs):

+
stateDiagram-v2
+    [*] --> Still
+    Still --> [*]
+
+    Still --> Moving
+    Moving --> Still
+    Moving --> Crash
+    Crash --> [*]
+

Class Diagram (Arbitrary)

+
classDiagram
+    class Animal
+    `NexusMobile™` <|-- Car
+
+

Note

+

At time of writing, version of Mermaid is a bit outdated here; and other diagrams might not render correctly +(even on unmodified theme); thus certain diagrams have been omitted from here.

+
+

Code Block

+

Snippet from C# version of Sewer's Virtual FileSystem (VFS):

+
/// <summary>
+/// Tries to get files for a specific folder, assuming the input path is already in upper case.
+/// </summary>
+/// <param name="folderPath">The folder to find. Already lowercase.</param>
+/// <param name="value">The returned folder instance.</param>
+/// <returns>True if found, else false.</returns>
+[MethodImpl(MethodImplOptions.AggressiveInlining)]
+public bool TryGetFolderUpper(ReadOnlySpan<char> folderPath, out SpanOfCharDict<TTarget> value)
+{
+    // Must be O(1)
+    value = default!;        
+
+    // Compare equality.
+    // Note to devs: Do not invert branches, we optimise for hot paths here.
+    if (folderPath.StartsWith(Prefix))
+    {
+        // Check for subfolder in branchless way.
+        // In CLR, bool is length 1, so conversion to byte should be safe.
+        // Even suppose it is not; as long as code is little endian; truncating int/4 bytes to byte still results 
+        // in correct answer.
+        var hasSubfolder = Prefix.Length != folderPath.Length;
+        var hasSubfolderByte = Unsafe.As<bool, byte>(ref hasSubfolder);
+        var nextFolder = folderPath.SliceFast(Prefix.Length + hasSubfolderByte);
+
+        return SubfolderToFiles.TryGetValue(nextFolder, out value!);
+    }
+
+    return false;
+}
+
+

Something more number heavy, Fast Inverse Square Root from Quake III Arena (unmodified). +

float Q_rsqrt( float number )
+{
+    long i;
+    float x2, y;
+    const float threehalfs = 1.5F;
+
+    x2 = number * 0.5F;
+    y  = number;
+    i  = * ( long * ) &y;                       // evil floating point bit level hacking
+    i  = 0x5f3759df - ( i >> 1 );               // what the fuck? 
+    y  = * ( float * ) &i;
+    y  = y * ( threehalfs - ( x2 * y * y ) );   // 1st iteration
+//  y  = y * ( threehalfs - ( x2 * y * y ) );   // 2nd iteration, this can be removed
+
+    return y;
+}
+

+

Default Admonitions

+
+

Note

+

Test

+
+
+

Abstract

+

Test

+
+
+

Info

+

Test

+
+
+

Tip

+

Test

+
+
+

Success

+

Test

+
+
+

Question

+

Test

+
+
+

Warning

+

Test

+
+
+

Failure

+

Test

+
+
+

Danger

+

Test

+
+
+

Bug

+

Test

+
+
+

Example

+

Test

+
+
+

Quote

+

Test

+
+

Tables

+ + + + + + + + + + + + + + + + + + + + + +
MethodDescription
GET Fetch resource
PUT Update resource
DELETE Delete resource
+ + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/Reloaded/docs/Stylesheets/Montserrat-Bold.ttf b/Reloaded/docs/Stylesheets/Montserrat-Bold.ttf new file mode 100644 index 0000000..efddc83 Binary files /dev/null and b/Reloaded/docs/Stylesheets/Montserrat-Bold.ttf differ diff --git a/Reloaded/docs/Stylesheets/Montserrat-Regular.ttf b/Reloaded/docs/Stylesheets/Montserrat-Regular.ttf new file mode 100644 index 0000000..aa9033a Binary files /dev/null and b/Reloaded/docs/Stylesheets/Montserrat-Regular.ttf differ diff --git a/Reloaded/docs/Stylesheets/Montserrat-SemiBold.ttf b/Reloaded/docs/Stylesheets/Montserrat-SemiBold.ttf new file mode 100644 index 0000000..cbf44db Binary files /dev/null and b/Reloaded/docs/Stylesheets/Montserrat-SemiBold.ttf differ diff --git a/Reloaded/docs/Stylesheets/extra.css b/Reloaded/docs/Stylesheets/extra.css new file mode 100644 index 0000000..b183a12 --- /dev/null +++ b/Reloaded/docs/Stylesheets/extra.css @@ -0,0 +1,597 @@ +/* + Nexus Mods Theme +*/ + +:root { + --md-admonition-icon--nexus: url('../Images/Nexus-Icon-40.png'); + --md-admonition-icon--nexusheart: url('../Images/Nexus-Heart-40.png'); + --md-admonition-icon--reloaded: url('../Images/Reloaded-Icon-40.png'); + --md-admonition-icon--reloadedheart: url('../Images/Reloaded-Heart-40.png'); +} + +/* Slate theme, i.e. dark mode */ + +[data-md-color-scheme="nexus-slate"] { + /* + Default Variables + */ + + /* For reuse later */ + --md-primary-fg-color-rgb: 217, 143, 64; + + /* Primary color shades */ + --md-primary-fg-color: #D98F40; + --md-primary-fg-color--light: #E0A362; + --md-primary-fg-color--dark: #C87B28; + + --md-primary-bg-color: #FFFFFF; + --md-primary-bg-color--light: #FFFFFFB2; + + /* Accent color shades */ + --md-accent-fg-color: #C87B28; + --md-accent-fg-color--transparent: #C87B2810; + + --md-accent-bg-color: #2A2C2B; + --md-accent-bg-color--light: #2A2C2B; + +/* + // Slate's hue in the range [0,360] - change this variable to alter the tone + // of the theme, e.g. to make it more redish or greenish. This is a slate- + // specific variable, but the same approach may be adapted to custom themes. +*/ + --md-hue: 31; + --nexus-background-primary: #101010; + --nexus-background-secondary: #181818; + --nexus-background-tertiary: #222222; + --nexus-background-content-primary: #1C1C1C; + --nexus-background-content-secondary: #2B2D2F; + + --nexus-font-primary: #FFFFFF; /* #FFFFFF */ + --nexus-font-secondary: #AAAAAA; /* #AAAAAA */ + --nexus-font-tertiary: #5A5A5A; /* #5A5A5A */ + + --nexus-font-primary-rgb: 255, 255, 255; /* #FFFFFF */ + --nexus-font-secondary-rgb: 170, 170, 170; /* #AAAAAA */ + --nexus-font-tertiary-rgb: 90, 90, 90; /* #5A5A5A */ + + /* Default color shades */ + --md-default-fg-color: var(--nexus-font-primary); + --md-default-fg-color--light: var(--nexus-font-secondary); + --md-default-fg-color--lighter: var(--nexus-font-tertiary); + --md-default-fg-color--lightest: rgba(var(--nexus-font-primary-rgb), 0.12); + --md-default-bg-color: var(--nexus-background-secondary); + --md-default-bg-color--light: var(--nexus-background-content-primary); + --md-default-bg-color--lighter: var(--nexus-background-tertiary); + --md-default-bg-color--lightest: var(--nexus-background-content-secondary); + + /* Code color shades */ + --md-code-fg-color: hsla(var(--md-hue), 18%, 86%, 1); + --md-code-bg-color: var(--nexus-background-content-secondary); + + /* Code highlighting color shades */ + --md-code-hl-color: #4287ff26; + --md-code-hl-number-color: hsla(219, 74%, 63%, 1); + --md-code-hl-special-color: hsla(340, 83%, 66%, 1); + --md-code-hl-function-color: hsla(219, 57%, 65%, 1); + --md-code-hl-constant-color: hsla(250, 62%, 70%, 1); + --md-code-hl-keyword-color: hsla(var(--md-hue), 66%, 64%, 1); + --md-code-hl-string-color: hsla(150, 58%, 44%, 1); + --md-code-hl-name-color: var(--md-code-fg-color); + --md-code-hl-operator-color: var(--md-default-fg-color--light); + --md-code-hl-punctuation-color: var(--md-default-fg-color--light); + --md-code-hl-comment-color: var(--md-default-fg-color--light); + --md-code-hl-generic-color: var(--md-default-fg-color--light); + --md-code-hl-variable-color: var(--md-default-fg-color--light); + + /* Typeset color shades */ + --md-typeset-color: var(--md-default-fg-color); + + /* Typeset `a` color shades */ + --md-typeset-a-color: var(--md-primary-fg-color); + + /* Typeset `mark` color shades */ + --md-typeset-mark-color: #4287ff4d; + + /* Typeset `kbd` color shades */ + --md-typeset-kbd-color: hsla(var(--md-hue), 15%, 94%, 0.12); + --md-typeset-kbd-accent-color: hsla(var(--md-hue), 15%, 94%, 0.2); + --md-typeset-kbd-border-color: hsla(var(--md-hue), 15%, 14%, 1); + + /* Typeset `table` color shades */ + --md-typeset-table-color: hsla(var(--md-hue), 75%, 95%, 0.12); + --md-typeset-table-color--light: hsla(var(--md-hue), 75%, 95%, 0.035); + + /* Admonition color shades */ + --md-admonition-fg-color: var(--md-default-fg-color); + --md-admonition-bg-color: var(--md-default-bg-color); + + /* Footer color shades */ + --md-footer-bg-color: var(--nexus-background-primary); + --md-footer-bg-color--dark: var(--nexus-background-primary); + + /* Shadow depth 1 */ + --md-shadow-z1: + 0 #{px2rem(4px)} #{px2rem(10px)} hsla(0, 0%, 0%, 0.2), + 0 0 #{px2rem(1px)} hsla(0, 0%, 0%, 0.1); + + /* Shadow depth 2 */ + --md-shadow-z2: + 0 #{px2rem(4px)} #{px2rem(10px)} hsla(0, 0%, 0%, 0.3), + 0 0 #{px2rem(1px)} hsla(0, 0%, 0%, 0.25); + + /* Shadow depth 3 */ + --md-shadow-z3: + 0 #{px2rem(4px)} #{px2rem(10px)} hsla(0, 0%, 0%, 0.4), + 0 0 #{px2rem(1px)} hsla(0, 0%, 0%, 0.35); + + /* Hide images for light mode */ + img[src$="#only-light"], + img[src$="#gh-light-mode-only"] { + display: none; + } + + /* Show images for dark mode */ + img[src$="#only-dark"], + img[src$="#gh-dark-mode-only"] { + display: initial; + } +} + +[data-md-color-scheme="nexus-slate"] .md-header { + background-color: var(--nexus-background-primary); +} + +[data-md-color-scheme="reloaded-slate"] { + /* + Default Variables + */ + + /* For reuse later */ + --md-primary-fg-color-rgb: 182, 99, 99; + + /* Primary color shades */ + --md-primary-fg-color: #793939; + --md-primary-fg-color--light: #B66363; + --md-primary-fg-color--lightest: #d6a8a8; + --md-primary-fg-color--dark: #572929; + + --md-primary-bg-color: #FFFFFF; + --md-primary-bg-color--light: #FFFFFFB2; + + /* Accent color shades */ + --md-accent-fg-color: #793939; + --md-accent-fg-color--transparent: #79393960; + + --md-accent-bg-color: #181818; + --md-accent-bg-color--light: #181818; + + /* + // Slate's hue in the range [0,360] - change this variable to alter the tone + // of the theme, e.g. to make it more redish or greenish. This is a slate- + // specific variable, but the same approach may be adapted to custom themes. + */ + --md-hue: 0; + --nexus-background-primary: #101010; + --nexus-background-secondary: #181818; + --nexus-background-tertiary: #222222; + --nexus-background-content-primary: #1C1C1C; + --nexus-background-content-secondary: #2B2D2F; + + --nexus-font-primary: #FFFFFF; /* #FFFFFF */ + --nexus-font-secondary: #AAAAAA; /* #AAAAAA */ + --nexus-font-tertiary: #5A5A5A; /* #5A5A5A */ + + --nexus-font-primary-rgb: 255, 255, 255; /* #FFFFFF */ + --nexus-font-secondary-rgb: 170, 170, 170; /* #AAAAAA */ + --nexus-font-tertiary-rgb: 90, 90, 90; /* #5A5A5A */ + + /* Default color shades */ + --md-default-fg-color: var(--nexus-font-primary); + --md-default-fg-color--light: var(--nexus-font-secondary); + --md-default-fg-color--lighter: var(--nexus-font-tertiary); + --md-default-fg-color--lightest: rgba(var(--nexus-font-primary-rgb), 0.04); + --md-default-bg-color: var(--nexus-background-secondary); + --md-default-bg-color--light: var(--nexus-background-content-primary); + --md-default-bg-color--lighter: var(--nexus-background-tertiary); + --md-default-bg-color--lightest: var(--nexus-background-content-secondary); + + /* Code color shades */ + --md-code-fg-color: hsla(var(--md-hue), 18%, 86%, 1); + --md-code-bg-color: var(--nexus-background-content-secondary); + + /* Code highlighting color shades */ + --md-code-hl-color: #4287ff26; + --md-code-hl-number-color: hsla(219, 74%, 63%, 1); + --md-code-hl-special-color: hsla(340, 83%, 66%, 1); + --md-code-hl-function-color: hsla(219, 57%, 65%, 1); + --md-code-hl-constant-color: hsla(250, 62%, 70%, 1); + --md-code-hl-keyword-color: hsla(var(--md-hue), 66%, 64%, 1); + --md-code-hl-string-color: hsla(150, 58%, 44%, 1); + --md-code-hl-name-color: var(--md-code-fg-color); + --md-code-hl-operator-color: var(--md-default-fg-color--light); + --md-code-hl-punctuation-color: var(--md-default-fg-color--light); + --md-code-hl-comment-color: var(--md-default-fg-color--light); + --md-code-hl-generic-color: var(--md-default-fg-color--light); + --md-code-hl-variable-color: var(--md-default-fg-color--light); + + /* Typeset color shades */ + --md-typeset-color: var(--md-default-fg-color); + + /* Typeset `a` color shades */ + --md-typeset-a-color: var(--md-primary-fg-color--lightest); + + /* Typeset `mark` color shades */ + --md-typeset-mark-color: #4287ff4d; + + /* Typeset `kbd` color shades */ + --md-typeset-kbd-color: hsla(var(--md-hue), 15%, 94%, 0.12); + --md-typeset-kbd-accent-color: hsla(var(--md-hue), 15%, 94%, 0.2); + --md-typeset-kbd-border-color: hsla(var(--md-hue), 15%, 14%, 1); + + /* Typeset `table` color shades */ + --md-typeset-table-color: hsla(var(--md-hue), 75%, 95%, 0.12); + --md-typeset-table-color--light: hsla(var(--md-hue), 75%, 95%, 0.035); + + /* Admonition color shades */ + --md-admonition-fg-color: var(--md-default-fg-color); + --md-admonition-bg-color: var(--md-default-bg-color); + + /* Footer color shades */ + --md-footer-bg-color: var(--nexus-background-primary); + --md-footer-bg-color--dark: var(--nexus-background-primary); + + /* Shadow depth 1 */ + --md-shadow-z1: + 0 #{px2rem(4px)} #{px2rem(10px)} hsla(0, 0%, 0%, 0.2), + 0 0 #{px2rem(1px)} hsla(0, 0%, 0%, 0.1); + + /* Shadow depth 2 */ + --md-shadow-z2: + 0 #{px2rem(4px)} #{px2rem(10px)} hsla(0, 0%, 0%, 0.3), + 0 0 #{px2rem(1px)} hsla(0, 0%, 0%, 0.25); + + /* Shadow depth 3 */ + --md-shadow-z3: + 0 #{px2rem(4px)} #{px2rem(10px)} hsla(0, 0%, 0%, 0.4), + 0 0 #{px2rem(1px)} hsla(0, 0%, 0%, 0.35); + + /* Hide images for light mode */ + img[src$="#only-light"], + img[src$="#gh-light-mode-only"] { + display: none; + } + + /* Show images for dark mode */ + img[src$="#only-dark"], + img[src$="#gh-dark-mode-only"] { + display: initial; + } +} + +[data-md-color-scheme="reloaded-slate"] .md-typeset a:hover { + color: var(--md-primary-fg-color--light); +} + +[data-md-color-scheme="reloaded-slate"] .md-nav--primary .md-nav__item--active>.md-nav__link:hover { + color: var(--md-primary-fg-color--light); +} + +[data-md-color-scheme="reloaded-slate"] .md-nav__link:hover { + color: var(--md-primary-fg-color--light); +} + + +[data-md-color-scheme="reloaded3-slate"] { + /* + Default Variables + */ + + /* For reuse later */ + --md-primary-fg-color-rgb: 63, 153, 217; + + /* Primary color shades */ + --md-primary-fg-color: #fa7774; + --md-primary-fg-color--light: #fc918b; + --md-primary-fg-color--dark: #e96060; + --md-primary-fg-color--darker: #d74f52; + --md-primary-fg-color--darkest: #c53e44; + + --md-primary-bg-color: #FFFFFF; + --md-primary-bg-color--light: #FFFFFFB2; + + /* Accent color shades */ + --md-accent-fg-color: #e96060; + --md-accent-fg-color--transparent: #e9606030; + + --md-accent-bg-color: #2A2C2B; + --md-accent-bg-color--light: #2A2C2B; + + /* + // Slate's hue in the range [0,360] - change this variable to alter the tone + // of the theme, e.g. to make it more redish or greenish. This is a slate- + // specific variable, but the same approach may be adapted to custom themes. + */ + --md-hue: 1; + --nexus-background-primary: #101010; + --nexus-background-secondary: #181818; + --nexus-background-tertiary: #222222; + --nexus-background-content-primary: #1C1C1C; + --nexus-background-content-secondary: #2B2D2F; + + --nexus-font-primary: #FFFFFF; /* #FFFFFF */ + --nexus-font-secondary: #AAAAAA; /* #AAAAAA */ + --nexus-font-tertiary: #5A5A5A; /* #5A5A5A */ + + --nexus-font-primary-rgb: 255, 255, 255; /* #FFFFFF */ + --nexus-font-secondary-rgb: 170, 170, 170; /* #AAAAAA */ + --nexus-font-tertiary-rgb: 90, 90, 90; /* #5A5A5A */ + + /* Default color shades */ + --md-default-fg-color: var(--nexus-font-primary); + --md-default-fg-color--light: var(--nexus-font-secondary); + --md-default-fg-color--lighter: var(--nexus-font-tertiary); + --md-default-fg-color--lightest: rgba(var(--nexus-font-primary-rgb), 0.12); + --md-default-bg-color: var(--nexus-background-secondary); + --md-default-bg-color--light: var(--nexus-background-content-primary); + --md-default-bg-color--lighter: var(--nexus-background-tertiary); + --md-default-bg-color--lightest: var(--nexus-background-content-secondary); + + /* Code color shades */ + --md-code-fg-color: hsla(var(--md-hue), 18%, 86%, 1); + --md-code-bg-color: var(--nexus-background-content-secondary); + + /* Code highlighting color shades */ + --md-code-hl-color: #4287ff26; + --md-code-hl-number-color: hsla(219, 74%, 63%, 1); + --md-code-hl-special-color: hsla(340, 83%, 66%, 1); + --md-code-hl-function-color: hsla(219, 57%, 65%, 1); + --md-code-hl-constant-color: hsla(250, 62%, 70%, 1); + --md-code-hl-keyword-color: hsla(var(--md-hue), 66%, 64%, 1); + --md-code-hl-string-color: hsla(150, 58%, 44%, 1); + --md-code-hl-name-color: var(--md-code-fg-color); + --md-code-hl-operator-color: var(--md-default-fg-color--light); + --md-code-hl-punctuation-color: var(--md-default-fg-color--light); + --md-code-hl-comment-color: var(--md-default-fg-color--light); + --md-code-hl-generic-color: var(--md-default-fg-color--light); + --md-code-hl-variable-color: var(--md-default-fg-color--light); + + /* Typeset color shades */ + --md-typeset-color: var(--md-default-fg-color); + + /* Typeset `a` color shades */ + --md-typeset-a-color: var(--md-primary-fg-color); + + /* Typeset `mark` color shades */ + --md-typeset-mark-color: #4287ff4d; + + /* Typeset `kbd` color shades */ + --md-typeset-kbd-color: hsla(var(--md-hue), 15%, 94%, 0.12); + --md-typeset-kbd-accent-color: hsla(var(--md-hue), 15%, 94%, 0.2); + --md-typeset-kbd-border-color: hsla(var(--md-hue), 15%, 14%, 1); + + /* Typeset `table` color shades */ + --md-typeset-table-color: hsla(var(--md-hue), 75%, 95%, 0.12); + --md-typeset-table-color--light: hsla(var(--md-hue), 75%, 95%, 0.035); + + /* Admonition color shades */ + --md-admonition-fg-color: var(--md-default-fg-color); + --md-admonition-bg-color: var(--md-default-bg-color); + + /* Footer color shades */ + --md-footer-bg-color: var(--nexus-background-primary); + --md-footer-bg-color--dark: var(--nexus-background-primary); + + /* Shadow depth 1 */ + --md-shadow-z1: + 0 #{px2rem(4px)} #{px2rem(10px)} hsla(0, 0%, 0%, 0.2), + 0 0 #{px2rem(1px)} hsla(0, 0%, 0%, 0.1); + + /* Shadow depth 2 */ + --md-shadow-z2: + 0 #{px2rem(4px)} #{px2rem(10px)} hsla(0, 0%, 0%, 0.3), + 0 0 #{px2rem(1px)} hsla(0, 0%, 0%, 0.25); + + /* Shadow depth 3 */ + --md-shadow-z3: + 0 #{px2rem(4px)} #{px2rem(10px)} hsla(0, 0%, 0%, 0.4), + 0 0 #{px2rem(1px)} hsla(0, 0%, 0%, 0.35); + + /* Hide images for light mode */ + img[src$="#only-light"], + img[src$="#gh-light-mode-only"] { + display: none; + } + + /* Show images for dark mode */ + img[src$="#only-dark"], + img[src$="#gh-dark-mode-only"] { + display: initial; + } +} + +[data-md-color-scheme="reloaded3-slate"] .md-header { + background-color: var(--md-primary-fg-color--darker); +} + +@media screen and (max-width: 76.1875em) { + /* Title in Drawer */ + [data-md-color-scheme="reloaded3-slate"] .md-nav--primary .md-nav__title[for=__drawer] { + background-color: var(--md-primary-fg-color--darker); + color: var(--md-primary-bg-color); + font-weight: 700; + } +} + +[data-md-color-scheme="reloaded3-slate"] .md-nav__source { + background-color: var(--md-primary-fg-color--darkest); + color: var(--md-primary-bg-color); +} + +.md-nav__title { + color: var(--md-default-fg-color); +} + +.md-nav__link { + color: var(--md-default-fg-color--light); +} + +/* Custom 'nexus' admonition */ +.md-typeset .admonition.nexus, +.md-typeset details.nexus { + border-color: var(--md-primary-fg-color); +} +.md-typeset .nexus > .admonition-title, +.md-typeset .nexus > summary { + background-color: rgba(var(--md-primary-fg-color-rgb), 0.1); +} +.md-typeset .nexus > .admonition-title::before, +.md-typeset .nexus > summary::before { + background-color: unset; + -webkit-mask-image: unset; + background-image: var(--md-admonition-icon--nexus); + background-size: contain; + background-repeat: no-repeat; + background-position: center; +} + +/* Custom 'nexus heart' admonition */ +.md-typeset .admonition.nexusheart, +.md-typeset details.nexusheart { + border-color: var(--md-primary-fg-color); +} +.md-typeset .nexusheart > .admonition-title, +.md-typeset .nexusheart > summary { + background-color: rgba(var(--md-primary-fg-color-rgb), 0.1); +} +.md-typeset .nexusheart > .admonition-title::before, +.md-typeset .nexusheart > summary::before { + background-color: unset; + -webkit-mask-image: unset; + background-image: var(--md-admonition-icon--nexusheart); + background-size: contain; + background-repeat: no-repeat; + background-position: center; +} + +/* Custom 'reloaded' admonition */ + +.md-typeset .admonition.reloaded, +.md-typeset details.reloaded { + border-color: var(--md-primary-fg-color); +} +.md-typeset .reloaded > .admonition-title, +.md-typeset .reloaded > summary { + background-color: rgba(var(--md-primary-fg-color-rgb), 0.1); +} +.md-typeset .reloaded > .admonition-title::before, +.md-typeset .reloaded > summary::before { + background-color: unset; + -webkit-mask-image: unset; + background-image: var(--md-admonition-icon--reloaded); + background-size: contain; + background-repeat: no-repeat; + background-position: center; +} + +/* Custom 'nexus heart' admonition */ +.md-typeset .admonition.reloadedheart, +.md-typeset details.reloadedheart { + border-color: var(--md-primary-fg-color); +} +.md-typeset .reloadedheart > .admonition-title, +.md-typeset .reloadedheart > summary { + background-color: rgba(var(--md-primary-fg-color-rgb), 0.1); +} +.md-typeset .reloadedheart > .admonition-title::before, +.md-typeset .reloadedheart > summary::before { + background-color: unset; + -webkit-mask-image: unset; + background-image: var(--md-admonition-icon--reloadedheart); + background-size: contain; + background-repeat: no-repeat; + background-position: center; +} + +/* Add Title Font */ +@font-face { + font-family: "Montserrat"; + src: url("./Montserrat-Regular.ttf") format("truetype"); + font-weight: normal; +} + +@font-face { + font-family: "Montserrat"; + src: url("./Montserrat-SemiBold.ttf") format("truetype"); + font-weight: 600; +} + +@font-face { + font-family: "Montserrat"; + src: url("./Montserrat-Bold.ttf") format("truetype"); + font-weight: bold; +} + +/* Headers */ +[data-md-color-scheme="nexus-slate"] .md-typeset h1 { + color: var(--md-default-fg-color); + font-family: "Montserrat",Roboto; + font-weight: 600; +} + +[data-md-color-scheme="nexus-slate"] .md-typeset h2 { + color: var(--md-default-fg-color); + font-family: "Montserrat",Roboto; + font-weight: 600; +} + +[data-md-color-scheme="nexus-slate"] .md-typeset h3 { + color: var(--md-default-fg-color); + font-family: "Montserrat",Roboto; + font-weight: 600; +} + +[data-md-color-scheme="nexus-slate"] .md-typeset h4 { + color: var(--md-default-fg-color); + font-family: "Montserrat",Roboto; + font-weight: 600; +} + +[data-md-color-scheme="nexus-slate"] .md-typeset h5 { + color: var(--md-default-fg-color); + font-family: "Montserrat",Roboto; + font-weight: 600; +} + +[data-md-color-scheme="reloaded-slate"] .md-typeset h1 { + color: var(--md-default-fg-color); +} + +[data-md-color-scheme="reloaded3-slate"] .md-typeset h1 { + color: var(--md-default-fg-color); + font-family: "Montserrat",Roboto; + font-weight: 600; +} + +[data-md-color-scheme="reloaded3-slate"] .md-typeset h2 { + color: var(--md-default-fg-color); + font-family: "Montserrat",Roboto; + font-weight: 600; +} + +[data-md-color-scheme="reloaded3-slate"] .md-typeset h3 { + color: var(--md-default-fg-color); + font-family: "Montserrat",Roboto; + font-weight: 600; +} + +[data-md-color-scheme="reloaded3-slate"] .md-typeset h4 { + color: var(--md-default-fg-color); + font-family: "Montserrat",Roboto; + font-weight: 600; +} + +[data-md-color-scheme="reloaded3-slate"] .md-typeset h5 { + color: var(--md-default-fg-color); + font-family: "Montserrat",Roboto; + font-weight: 600; +} \ No newline at end of file diff --git a/Reloaded/mkdocs.yml b/Reloaded/mkdocs.yml new file mode 100644 index 0000000..bf04100 --- /dev/null +++ b/Reloaded/mkdocs.yml @@ -0,0 +1,58 @@ +site_name: Reloaded MkDocs Theme +site_url: https://github.com/Reloaded-Project/Reloaded.MkDocsMaterial.Themes.R2 + +repo_name: Reloaded-Project/Reloaded.MkDocsMaterial.Themes.R2 +repo_url: https://github.com/Reloaded-Project/Reloaded.MkDocsMaterial.Themes.R2 + +extra: + social: + - icon: fontawesome/brands/github + link: https://github.com/Reloaded-Project + - icon: fontawesome/brands/twitter + link: https://twitter.com/thesewer56?lang=en-GB + +extra_css: + - Stylesheets/extra.css + +markdown_extensions: + - admonition + - tables + - pymdownx.details + - pymdownx.highlight + - pymdownx.superfences: + custom_fences: + - name: mermaid + class: mermaid + format: !!python/name:pymdownx.superfences.fence_code_format + - pymdownx.tasklist + - def_list + - meta + - md_in_html + - attr_list + - footnotes + - pymdownx.tabbed: + alternate_style: true + - pymdownx.emoji: + emoji_index: !!python/name:materialx.emoji.twemoji + emoji_generator: !!python/name:materialx.emoji.to_svg + +theme: + name: material + palette: + scheme: reloaded3-slate + features: + - navigation.instant + +plugins: + - search + - redirects: + redirect_maps: + 'index.md': 'Pages/index.md' + +nav: + - Home: Pages/index.md + - License: Pages/license.md + - Contributing: Pages/contributing.md + - Testing Zone: Pages/testing-zone.md + +index: Pages/index.md \ No newline at end of file diff --git a/Streams/BufferedStreamReader/index.html b/Streams/BufferedStreamReader/index.html new file mode 100644 index 0000000..daeeff1 --- /dev/null +++ b/Streams/BufferedStreamReader/index.html @@ -0,0 +1,2184 @@ + + + + + + + + + + + + + + + + + + + + + + + + BufferedStreamReader - Reloaded Memory Library + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

BufferedStreamReader Class

+
+

The BufferedStreamReader is a buffering mechanism for reading data from streams, allowing for fast reading of data while preserving stream-like semantics.

+
+
+

BufferedStreamReader is a high-performance replacement for BinaryReader with minimal error checking.

+
+
+

BufferedStreamReader is not thread-safe.

+
+
+

BufferedStreamReader cannot read values larger than buffer size it was initialised with.

+
+
+

BufferedStreamReader has minimal error checking at runtime.

+
+
+

Tip

+

Remember, always ensure the stream and reader are properly disposed of after use. +The best practice is to use the using statement or try-finally block in C# to ensure resources are correctly released.

+
+

Performance

+

Amount of time taken to read 8 MiB of data (library version 9.0.0):

+

Legend:
+- BinaryReader read via BinaryReader.
+- BufferedStreamReader read via BufferedStreamReader.
+- BufferedStreamReader read via BufferedStreamReader (ReadRaw method).
+- NativePointer no stream; no copy; access existing data from array (baseline reference).

+

MemoryStream

+

Benchmarks on MemoryStream (near zero overhead) allow us to compare the performance against BinaryReader and +array access (baseline reference).

+

Byte:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodMeanCode Size
BinaryReader15,452.7 us171 B
BufferedStreamReader6,298.7 us703 B
BufferedStreamReader Raw1,997.3 us669 B
NativePointer1,845.2 us38 B
+

Int:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodMeanCode Size
BinaryReader3,253.2 us637 B
BufferedStreamReader1,708.7 us981 B
BufferedStreamReader Raw606.8 us760 B
NativePointer464.1 us54 B
+

Long:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodMeanCode Size
BinaryReader1,665.2 us639 B
BufferedStreamReader890.8 us709 B
BufferedStreamReader Raw370.7 us761 B
NativePointer227.3 us55 B
+

FileStream

+

Benchmarks on FileStream allow us to compare the performance against BinaryReader more closely.

+

Byte:

+ + + + + + + + + + + + + + + + + + + + + + + + + +
MethodMeanCode Size
BinaryReader21,309.7 us169 B
BufferedStreamReader6,731.9 us1,052 B
BufferedStreamReader Raw2,763.3 us661 B
+

Int:

+ + + + + + + + + + + + + + + + + + + + + + + + + +
MethodMeanCode Size
BinaryReader22,279.2 us640 B
BufferedStreamReader2,219.4 us1,487 B
BufferedStreamReader Raw1,310.4 us753 B
+

Long:

+ + + + + + + + + + + + + + + + + + + + + + + + + +
MethodMeanCode Size
BinaryReader13,025.8 us642 B
BufferedStreamReader1,425.6 us1,068 B
BufferedStreamReader Raw943.7 us754 B
+

Properties

+
    +
  • BaseStream: The stream this class was instantiated with.
  • +
  • BufferBytesAvailable: The remaining number of bytes that are currently buffered.
  • +
  • CurrentBufferSize: The total size of the current buffered data at this moment in time.
  • +
  • IsEndOfStream: This is true if end of stream was reached while refilling the internal buffer.
  • +
  • OnEndOfStream: This method is executed if a buffer refill does not fill the whole buffer, indicating end of stream was reached.
  • +
+

Constructors

+
    +
  • BufferedStreamReader(TStream stream, int bufferSize = 65536): Constructs a BufferedStreamReader.
  • +
+

Methods

+
+

Just like with regular Stream APIs, less data can be returned than requested if end of stream was reached. Please note BufferedStreamReader does not throw in these scenarios.

+
+

Seek

+
public void Seek(long offset, SeekOrigin origin)
+
+

Seeks the underlying stream to a specified position.

+

Advance

+
public void Advance(long offset)
+
+

Advances the underlying stream by a specified number of bytes.
+(This is equivalent to Seek(offset, SeekOrigin.Current))

+

Read

+
public T Read<T>() where T : unmanaged
+public void Read<T>(out T value) where T : unmanaged
+
+

Reads an unmanaged, generic type from the stream.

+

ReadRaw

+
+

The returned values point to internal buffers. DO NOT MODIFY THE DATA!

+
+
public byte* ReadRaw(int length, out int available)
+public T* ReadRaw<T>(int numItems, out int available) where T : unmanaged
+
+

Provides a pointer to the buffered data; buffering sufficient data if needed.

+

ReadRaw (with Output)

+
+

Variant of ReadRaw that copies the data to user's own destination.

+
+
public int ReadRaw<T>(Span<T> buffer) where T : unmanaged
+public int ReadRaw<T>(T* buffer, int numItems) where T : unmanaged
+
+

Reads raw data from the stream, without conversion. The output is written to the supplied pointer or span.

+

ReadBytesUnbuffered

+
+

This method is useful for reading large blobs (e.g. a compressed file from an archive) without discarding the buffered data.

+
+
public int ReadBytesUnbuffered(long offset, Span<byte> data)
+
+

Reads a specified amount of bytes at a specific offset from the underlying stream without resetting the buffers or advancing the read pointer.

+

ReadMarshalled

+
public T ReadMarshalled<T>()
+
+

Reads a value that requires marshalling from the stream.

+

Peek

+
public T Peek<T>() where T : unmanaged
+public void Peek<T>(out T value) where T : unmanaged
+
+

Reads an unmanaged, generic type from the stream without incrementing the position.

+

PeekMarshalled

+
public T PeekMarshalled<T>()
+public void PeekMarshalled<T>(out T value)
+
+

Reads a value that requires marshalling from the stream without advancing the position.

+

Methods (Endian Extensions)

+

PeekLittleEndian

+
public Int16 PeekLittleEndianInt16()
+public Int16 PeekLittleEndian(out Int16 value)
+public UInt16 PeekLittleEndianUInt16()
+public UInt16 PeekLittleEndian(out UInt16 value)
+public Int32 PeekLittleEndianInt32()
+public Int32 PeekLittleEndian(out Int32 value)
+public UInt32 PeekLittleEndianUInt32()
+public UInt32 PeekLittleEndian(out UInt32 value)
+public Int64 PeekLittleEndianInt64()
+public Int64 PeekLittleEndian(out Int64 value)
+public UInt64 PeekLittleEndianUInt64()
+public UInt64 PeekLittleEndian(out UInt64 value)
+public Single PeekLittleEndianSingle()
+public Single PeekLittleEndian(out Single value)
+public Double PeekLittleEndianDouble()
+public Double PeekLittleEndian(out Double value)
+
+

Peeks a little endian value of the specified type from the stream without incrementing the position.

+

PeekBigEndian

+
public Int16 PeekBigEndianInt16()
+public Int16 PeekBigEndian(out Int16 value)
+public UInt16 PeekBigEndianUInt16()
+public UInt16 PeekBigEndian(out UInt16 value)
+public Int32 PeekBigEndianInt32()
+public Int32 PeekBigEndian(out Int32 value)
+public UInt32 PeekBigEndianUInt32()
+public UInt32 PeekBigEndian(out UInt32 value)
+public Int64 PeekBigEndianInt64()
+public Int64 PeekBigEndian(out Int64 value)
+public UInt64 PeekBigEndianUInt64()
+public UInt64 PeekBigEndian(out UInt64 value)
+public Single PeekBigEndianSingle()
+public Single PeekBigEndian(out Single value)
+public Double PeekBigEndianDouble()
+public Double PeekBigEndian(out Double value)
+
+

Peeks a big endian value of the specified type from the stream without incrementing the position.

+

ReadLittleEndian

+
public Int16 ReadLittleEndianInt16()
+public Int16 ReadLittleEndian(out Int16 value)
+public UInt16 ReadLittleEndianUInt16()
+public UInt16 ReadLittleEndian(out UInt16 value)
+public Int32 ReadLittleEndianInt32()
+public Int32 ReadLittleEndian(out Int32 value)
+public UInt32 ReadLittleEndianUInt32()
+public UInt32 ReadLittleEndian(out UInt32 value)
+public Int64 ReadLittleEndianInt64()
+public Int64 ReadLittleEndian(out Int64 value)
+public UInt64 ReadLittleEndianUInt64()
+public UInt64 ReadLittleEndian(out UInt64 value)
+public Single ReadLittleEndianSingle()
+public Single ReadLittleEndian(out Single value)
+public Double ReadLittleEndianDouble()
+public Double ReadLittleEndian(out Double value)
+
+

Reads a little endian value of the specified type from the stream and advances the position by the size of the type.

+

ReadBigEndian

+
public Int16 ReadBigEndianInt16()
+public Int16 ReadBigEndian(out Int16 value)
+public UInt16 ReadBigEndianUInt16()
+public UInt16 ReadBigEndian(out UInt16 value)
+public Int32 ReadBigEndianInt32()
+public Int32 ReadBigEndian(out Int32 value)
+public UInt32 ReadBigEndianUInt32()
+public UInt32 ReadBigEndian(out UInt32 value)
+public Int64 ReadBigEndianInt64()
+public Int64 ReadBigEndian(out Int64 value)
+public UInt64 ReadBigEndianUInt64()
+public UInt64 ReadBigEndian(out UInt64 value)
+public Single ReadBigEndianSingle()
+public Single ReadBigEndian(out Single value)
+public Double ReadBigEndianDouble()
+public Double ReadBigEndian(out Double value)
+
+

Reads a big endian value of the specified type from the stream and advances the position by the size of the type.

+

AsLittleEndian

+
+

Implements, IEndianedBufferStreamReader<TStream>. Use constraint where T : IEndianedBufferStreamReader<TStream> to write endian agnostic code without any overhead.

+
+
public LittleEndianBufferedStreamReader<TStream> AsLittleEndian();
+
+

Returns a reader that can be used to read little endian values from the stream.

+

AsBigEndian

+
+

Implements, IEndianedBufferStreamReader<TStream>. Use constraint where T : IEndianedBufferStreamReader<TStream> to write endian agnostic code without any overhead.

+
+
public BigEndianBufferedStreamReader<TStream> AsBigEndian();
+
+

Returns a reader that can be used to read big endian values from the stream.

+

Methods (Endian Struct Extensions)

+
+

The following methods are valid for structs which implement ICanReverseEndian

+
+

PeekLittleEndianStruct

+
public T PeekLittleEndianStruct<T>() where T : unmanaged, ICanReverseEndian
+public void PeekLittleEndianStruct<T>(out T value) where T : unmanaged, ICanReverseEndian
+
+

Peeks a little endian unmanaged, generic type from the stream without incrementing the position.

+

PeekBigEndianStruct

+
public T PeekBigEndianStruct<T>() where T : unmanaged, ICanReverseEndian
+public void PeekBigEndianStruct<T>(out T value) where T : unmanaged, ICanReverseEndian
+
+

Peeks a big endian unmanaged, generic type from the stream without incrementing the position.

+

ReadLittleEndianStruct

+
public T ReadLittleEndianStruct<T>() where T : unmanaged, ICanReverseEndian
+public void ReadLittleEndianStruct<T>(out T value) where T : unmanaged, ICanReverseEndian
+
+

Reads a little endian unmanaged, generic type from the stream.

+

ReadBigEndianStruct

+
public T ReadBigEndianStruct<T>() where T : unmanaged, ICanReverseEndian
+public void ReadBigEndianStruct<T>(out T value) where T : unmanaged, ICanReverseEndian
+
+

Reads a big endian unmanaged, generic type from the stream.

+

Examples

+

Creating a BufferedStreamReader

+
var stream = File.OpenRead("myFile.txt");
+using var reader = new BufferedStreamReader<FileStream>(stream);
+
+

Reading an Integer from the Stream

+
int value = reader.Read<int>();
+Console.WriteLine($"Read value: {value}");
+
+

Reading Raw Bytes

+
+

Do not modify the returned data! Copy it elsewhere first!

+
+
int length = 10;
+int available;
+byte* rawBytes = reader.ReadRaw(length, out available);
+
+

Reading Raw Structs

+
using var reader = new BufferedStreamReader<FileStream>(fileStream);
+Span<Vector3> span = stackalloc Vector3[10];
+int readItems = reader.ReadRaw(span);
+
+Console.WriteLine($"{readItems} Vector3 items were read from the stream.");
+
+

In this example, we create a BufferedStreamReader using a FileStream and then declare a Span<Vector3> where Vector3 +is a struct representing a 3D vector. We then read from the stream directly into the Span<Vector3>. After reading, we +print out how many Vector3 items were read from the stream.

+

Seeking and Advancing Stream

+
var reader = new BufferedStreamReader<FileStream>(fileStream);
+reader.Seek(100, SeekOrigin.Begin); // Seek to 100 bytes from the start
+reader.Advance(50); // Advance 50 bytes from the current position
+
+Console.WriteLine($"Current stream position is {reader.Position()}");
+
+

In this example, we first seek to 100 bytes from the start of the stream. Then we advance 50 bytes from the current position. After that, we print out the current stream position.

+

Reading Unmanaged Types

+
using var reader = new BufferedStreamReader<FileStream>(fileStream);
+int value = reader.Read<int>(); // Reads an integer from the stream
+
+Console.WriteLine($"The read integer value is {value}");
+
+

In this example, we read an integer directly from the stream and print it out.

+

Reading Large Raw Data

+
using var reader = new BufferedStreamReader<FileStream>(fileStream);
+Span<byte> dataSpan = stackalloc byte[1024];
+int bytesRead = reader.ReadBytesUnbuffered(200, dataSpan);
+
+Console.WriteLine($"{bytesRead} bytes were read from the stream.");
+
+

In this example, we read 1024 bytes starting from 200 bytes offset into a Span<byte> without resetting the buffers or +advancing the read pointer. After reading, we print out how many bytes were read from the stream.

+
+

Value of bytesRead may be less than length of dataSpan if end of stream was reached.

+
+

Peeking Data

+
using var reader = new BufferedStreamReader<FileStream>(fileStream);
+int value = reader.Peek<int>(); // Peeks an integer from the stream
+
+Console.WriteLine($"The peeked integer value is {value}. Stream did not advance.");
+
+

Using Customized Buffer Size

+
+

The default buffer size of 64KBytes should be sufficient for most use cases, including file reads.

+
+
int bufferSize = 8192; // 8 KB
+using var reader = new BufferedStreamReader<FileStream>(fileStream, bufferSize);
+
+Console.WriteLine($"Custom buffer size of {bufferSize} bytes is used for the reader.");
+
+

In this example, a custom buffer size is set when creating a BufferedStreamReader. This allows you to tune the buffer +size to match your specific use case, potentially improving performance.

+

Combining Multiple Operations

+
var reader = new BufferedStreamReader<FileStream>(fileStream);
+reader.Seek(100, SeekOrigin.Begin); 
+int value = reader.Read<int>(); 
+reader.Advance(50); 
+Vector3 vector = reader.Read<Vector3>();
+
+Console.WriteLine($"Read integer value: {value}, Vector3: {vector.X}, {vector.Y}, {vector.Z}.");
+
+

In this final example, multiple operations are combined. First, the reader seeks to a specific position in the stream. +Then, an integer is read, the reader advances a certain number of bytes, and finally, a Vector3 struct is read. +The results are then printed to the console.

+

Examples (Extensions)

+

Writing Endian Agnostic Code

+
+

Shows you how to write code that works with both Big and Little Endian data.

+
+
using var reader = new BufferedStreamReader<FileStream>(fileStream);
+
+// Read in Big Endian
+Read(reader.AsBigEndian());
+// or... as Little Endian
+Read(reader.AsLittleEndian());
+
+private void Read<TReader>(TReader reader) where TReader : IEndianedBufferStreamReader
+{
+    // Some neat parsing code here.
+    var i16 = reader.ReadInt16();
+    var i32 = reader.PeekInt32();
+}
+
+

This approach allows you to write code which uses the same logic for both big and little endian.
+You can either pass reader.AsLittleEndian() or reader.AsBigEndian() to your parsing code. Either way, your reader +will be devirtualized and you'll be able to parse away with 0 overhead.

+

Reading Big/Little Endian Primitives

+
using var reader = new BufferedStreamReader<FileStream>(fileStream);
+
+// Little Endian
+Int16 littleEndianInt16 = reader.PeekLittleEndianInt16();
+Console.WriteLine($"The read Int16 value at offset 0 in Little Endian is {littleEndianInt16}");
+
+// Big Endian
+Int16 bigEndianInt16 = reader.PeekBigEndianInt16();
+Console.WriteLine($"The read Int16 value at offset 0 in Big Endian is {bigEndianInt16}");
+
+

Examples (Endian Struct Extensions)

+
+

CustomStruct must implement ICanReverseEndian

+
+

Example:

+
public struct CustomStruct : ICanReverseEndian
+{
+    public int Value1;
+    public int Value2;
+    public int Value3;
+
+    // ICanReverseEndian
+    public void ReverseEndian()
+    {
+        Value1 = Endian.Reverse(Value1);
+        Value2 = Endian.Reverse(Value2);
+        Value3 = Endian.Reverse(Value3);
+    }
+}
+
+

Reading a Little Endian Struct

+
using var reader = new BufferedStreamReader<FileStream>(fileStream);
+var value = reader.ReadLittleEndianStruct<CustomStruct>();
+
+Console.WriteLine($"The read CustomStruct value is {value}");
+
+

In this example, a CustomStruct is read directly from the stream using little endian byte order.

+

Reading a Big Endian Struct

+
using var reader = new BufferedStreamReader<FileStream>(fileStream);
+var value = reader.ReadBigEndianStruct<CustomStruct>();
+
+Console.WriteLine($"The read CustomStruct value is {value}");
+
+

In this example, a CustomStruct is read directly from the stream using big endian byte order.

+

Peeking a Little Endian Struct

+
using var reader = new BufferedStreamReader<FileStream>(fileStream);
+var value = reader.PeekLittleEndianStruct<CustomStruct>();
+
+Console.WriteLine($"The peeked CustomStruct value is {value}. Stream did not advance.");
+
+

In this example, a CustomStruct is peeked from the stream without advancing the stream position, using little endian byte order.

+

Peeking a Big Endian Struct

+
using var reader = new BufferedStreamReader<FileStream>(fileStream);
+var value = reader.PeekBigEndianStruct<CustomStruct>();
+
+Console.WriteLine($"The peeked CustomStruct value is {value}. Stream did not advance.");
+
+

In this example, a CustomStruct is peeked from the stream without advancing the stream position, using big endian byte order.

+
+

CustomStruct must be an unmanaged type and implement ICanReverseEndian interface.

+
+ + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/Streams/EndianReaders/About/index.html b/Streams/EndianReaders/About/index.html new file mode 100644 index 0000000..6a44295 --- /dev/null +++ b/Streams/EndianReaders/About/index.html @@ -0,0 +1,994 @@ + + + + + + + + + + + + + + + + + + + + + + + + About - Reloaded Memory Library + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

About

+
+

Common Info About Endian Readers and Writers

+
+

Interfaces

+
+

Structs can implement ICanBeReadByAnEndianReader and ICanWriteToAnEndianWriter to allow for easy reading and writing.

+
+

Example:

+

About the Offset Methods

+
+

The structs provide methods named WriteAtOffset / ReadAtOffset to operate on an offset of the current pointer without advancing the pointer itself.

+
+

These methods offer some minor performance advantages.

+

Improved Pipelining

+

By reducing the dependency of future instructions on earlier instructions, these offset methods allow for better pipelining. +For example, a future read operation does not need to wait for the Ptr value to be updated from a previous operation.

+

JIT Optimization

+

The Just-In-Time (JIT) compiler can recognize when the offset parameters are specified as constants and can optimize +the instructions accordingly. This can lead to more efficient code execution.

+
writer.WriteAtOffset(Hash, 0);
+writer.WriteAtOffset((int)DecompressedSize, 8);
+writer.WriteAtOffset(new OffsetPathIndexTuple(DecompressedBlockOffset, FilePathIndex, FirstBlockIndex).Data, 12);
+writer.Seek(NativeFileEntryV0.SizeBytes);
+
+

Because write on line 1, does not depend on modified pointer after line 0, execution is faster, as the CPU can +better pipeline the instructions as there is no dependency on the ptr result of the previous method call.

+ + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/Streams/EndianReaders/BigEndianReader/index.html b/Streams/EndianReaders/BigEndianReader/index.html new file mode 100644 index 0000000..8a83304 --- /dev/null +++ b/Streams/EndianReaders/BigEndianReader/index.html @@ -0,0 +1,1113 @@ + + + + + + + + + + + + + + + + + + + + + + + + BigEndianReader - Reloaded Memory Library + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

BigEndianReader

+
+

A struct for reading from a pointer in Big Endian.

+
+
+

BigEndianReader is preferred over BufferedStreamReader when all data is already in memory.

+
+

The BigEndianReader struct provides utility methods for reading various data types from a pointer in Big Endian format.

+

Methods

+

Read Methods

+

These methods read the specified data type from the current pointer in Big Endian format and advance the pointer.

+
public byte ReadByte()
+public sbyte ReadSByte()
+public short ReadShort()
+public ushort ReadUShort()
+public uint ReadUInt()
+public int ReadInt()
+public ulong ReadULong()
+public long ReadLong()
+public float ReadFloat()
+public double ReadDouble()
+
+

ReadAtOffset Methods

+

These methods read the specified data type from the specified offset in Big Endian format without advancing the pointer.

+
public byte ReadByteAtOffset(int offset)
+public sbyte ReadSByteAtOffset(int offset)
+public short ReadShortAtOffset(int offset)
+public ushort ReadUShortAtOffset(int offset)
+public uint ReadUIntAtOffset(int offset)
+public int ReadIntAtOffset(int offset)
+public ulong ReadULongAtOffset(int offset)
+public long ReadLongAtOffset(int offset)
+public float ReadFloatAtOffset(int offset)
+public double ReadDoubleAtOffset(int offset)
+
+

Seek Method

+

This method advances the pointer by a specified number of bytes.

+
public void Seek(int offset)
+
+

About the Offset Methods

+

The BigEndianReader struct provides several methods that read from a specific offset without advancing the pointer. +These methods include ReadShortAtOffset, ReadIntAtOffset, ReadLongAtOffset, and ReadUlongAtOffset.

+

While these methods do not significantly reduce the instruction count, they offer some minor performance advantages, +you can read more about this in About Section

+

Usage

+

Reading from Pointer

+
BigEndianReader reader = new BigEndianReader(GetPointer());
+
+byte byteValue = reader.ReadByte();
+uint uintValue = reader.ReadUInt();
+double doubleValue = reader.ReadDouble();
+
+

Reading from Offset

+
BigEndianReader reader = new BigEndianReader(GetPointer());
+
+byte byteValue = reader.ReadByteAtOffset(5);
+uint uintValue = reader.ReadUIntAtOffset(10);
+double doubleValue = reader.ReadDoubleAtOffset(15);
+
+

Advancing the Pointer

+
BigEndianReader reader = new BigEndianReader(GetPointer(););
+
+reader.Seek(10); // Advances the pointer by 10 bytes.
+
+ + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/Streams/EndianReaders/BigEndianWriter/index.html b/Streams/EndianReaders/BigEndianWriter/index.html new file mode 100644 index 0000000..58d00de --- /dev/null +++ b/Streams/EndianReaders/BigEndianWriter/index.html @@ -0,0 +1,1136 @@ + + + + + + + + + + + + + + + + + + + + + + + + BigEndianWriter - Reloaded Memory Library + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

BigEndianWriter

+
+

Utility struct for writing to a pointer in Big Endian.

+
+

BigEndianWriter is a struct providing methods for writing various types of data to a memory location, with the data +being written in Big Endian byte order. This includes writing integers, floating point values, and arrays of bytes, +either advancing the pointer after each write or writing at a specific offset without advancing the pointer.

+

Properties

+

Ptr

+
public byte* Ptr;
+
+

Current pointer being written to.

+

Constructors

+

BigEndianWriter

+
public BigEndianWriter(byte* ptr)
+
+

Creates a simple wrapper around a pointer that writes in Big Endian. ptr is the pointer to the item behind the writer.

+

Methods

+

Write

+
public void Write(sbyte value)
+public void Write(byte value)
+public void Write(short value)
+public void Write(ushort value)
+public void Write(int value)
+public void Write(uint value)
+public void Write(long value)
+public void Write(ulong value)
+public void Write(float value)
+public void Write(double value)
+public void Write(Span<byte> data)
+
+

Writes a value to the current pointer and advances the pointer. Overloads exist for various data types including sbyte, byte, short, ushort, int, uint, long, ulong, float, double, and Span<byte>.

+

WriteAtOffset

+
public void WriteAtOffset(sbyte value, int offset)
+public void WriteAtOffset(byte value, int offset)
+public void WriteAtOffset(short value, int offset)
+public void WriteAtOffset(ushort value, int offset)
+public void WriteAtOffset(int value, int offset)
+public void WriteAtOffset(uint value, int offset)
+public void WriteAtOffset(long value, int offset)
+public void WriteAtOffset(ulong value, int offset)
+public void WriteAtOffset(float value, int offset)
+public void WriteAtOffset(double value, int offset)
+
+

Writes a value to the specified offset without advancing the pointer. Overloads exist for various data types including sbyte, byte, short, ushort, int, uint, long, ulong, float, double.

+

Seek

+
public void Seek(int offset)
+
+

Advances the stream by a specified number of bytes. offset is the number of bytes to advance by.

+

About the Offset Methods

+

The BigEndianWriter struct provides several methods that operate on a specific offset without advancing the pointer.

+

While these methods do not significantly reduce the instruction count, they offer some minor performance advantages, +you can read more about this in About Section

+

Usage

+

Example usage of the BigEndianWriter struct:

+
var writer = new BigEndianWriter(ptr);
+
+writer.Write((int)12345);  // Write an int
+writer.Write((byte)65);    // Write a byte
+writer.WriteAtOffset((long)9876543210, 5);  // Write a long at offset 5 from current pointer
+
+ + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/Streams/EndianReaders/LittleEndianReader/index.html b/Streams/EndianReaders/LittleEndianReader/index.html new file mode 100644 index 0000000..9f1486e --- /dev/null +++ b/Streams/EndianReaders/LittleEndianReader/index.html @@ -0,0 +1,1113 @@ + + + + + + + + + + + + + + + + + + + + + + + + LittleEndianReader - Reloaded Memory Library + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

LittleEndianReader

+
+

A struct for reading from a pointer in Big Endian.

+
+
+

LittleEndianReader is preferred over BufferedStreamReader when all data is already in memory.

+
+

The LittleEndianReader struct provides utility methods for reading various data types from a pointer in Big Endian format.

+

Methods

+

Read Methods

+

These methods read the specified data type from the current pointer in Big Endian format and advance the pointer.

+
public byte ReadByte()
+public sbyte ReadSByte()
+public short ReadShort()
+public ushort ReadUShort()
+public uint ReadUInt()
+public int ReadInt()
+public ulong ReadULong()
+public long ReadLong()
+public float ReadFloat()
+public double ReadDouble()
+
+

ReadAtOffset Methods

+

These methods read the specified data type from the specified offset in Big Endian format without advancing the pointer.

+
public byte ReadByteAtOffset(int offset)
+public sbyte ReadSByteAtOffset(int offset)
+public short ReadShortAtOffset(int offset)
+public ushort ReadUShortAtOffset(int offset)
+public uint ReadUIntAtOffset(int offset)
+public int ReadIntAtOffset(int offset)
+public ulong ReadULongAtOffset(int offset)
+public long ReadLongAtOffset(int offset)
+public float ReadFloatAtOffset(int offset)
+public double ReadDoubleAtOffset(int offset)
+
+

Seek Method

+

This method advances the pointer by a specified number of bytes.

+
public void Seek(int offset)
+
+

About the Offset Methods

+

The LittleEndianReader struct provides several methods that read from a specific offset without advancing the pointer. +These methods include ReadShortAtOffset, ReadIntAtOffset, ReadLongAtOffset, and ReadUlongAtOffset.

+

While these methods do not significantly reduce the instruction count, they offer some minor performance advantages, +you can read more about this in About Section

+

Usage

+

Reading from Pointer

+
LittleEndianReader reader = new LittleEndianReader(GetPointer());
+
+byte byteValue = reader.ReadByte();
+uint uintValue = reader.ReadUInt();
+double doubleValue = reader.ReadDouble();
+
+

Reading from Offset

+
LittleEndianReader reader = new LittleEndianReader(GetPointer());
+
+byte byteValue = reader.ReadByteAtOffset(5);
+uint uintValue = reader.ReadUIntAtOffset(10);
+double doubleValue = reader.ReadDoubleAtOffset(15);
+
+

Advancing the Pointer

+
LittleEndianReader reader = new LittleEndianReader(GetPointer(););
+
+reader.Seek(10); // Advances the pointer by 10 bytes.
+
+ + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/Streams/EndianReaders/LittleEndianWriter/index.html b/Streams/EndianReaders/LittleEndianWriter/index.html new file mode 100644 index 0000000..bc2dbe8 --- /dev/null +++ b/Streams/EndianReaders/LittleEndianWriter/index.html @@ -0,0 +1,1136 @@ + + + + + + + + + + + + + + + + + + + + + + + + LittleEndianWriter - Reloaded Memory Library + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

LittleEndianWriter

+
+

Utility struct for writing to a pointer in Big Endian.

+
+

LittleEndianWriter is a struct providing methods for writing various types of data to a memory location, with the data +being written in Big Endian byte order. This includes writing integers, floating point values, and arrays of bytes, +either advancing the pointer after each write or writing at a specific offset without advancing the pointer.

+

Properties

+

Ptr

+
public byte* Ptr;
+
+

Current pointer being written to.

+

Constructors

+

LittleEndianWriter

+
public LittleEndianWriter(byte* ptr)
+
+

Creates a simple wrapper around a pointer that writes in Big Endian. ptr is the pointer to the item behind the writer.

+

Methods

+

Write

+
public void Write(sbyte value)
+public void Write(byte value)
+public void Write(short value)
+public void Write(ushort value)
+public void Write(int value)
+public void Write(uint value)
+public void Write(long value)
+public void Write(ulong value)
+public void Write(float value)
+public void Write(double value)
+public void Write(Span<byte> data)
+
+

Writes a value to the current pointer and advances the pointer. Overloads exist for various data types including sbyte, byte, short, ushort, int, uint, long, ulong, float, double, and Span<byte>.

+

WriteAtOffset

+
public void WriteAtOffset(sbyte value, int offset)
+public void WriteAtOffset(byte value, int offset)
+public void WriteAtOffset(short value, int offset)
+public void WriteAtOffset(ushort value, int offset)
+public void WriteAtOffset(int value, int offset)
+public void WriteAtOffset(uint value, int offset)
+public void WriteAtOffset(long value, int offset)
+public void WriteAtOffset(ulong value, int offset)
+public void WriteAtOffset(float value, int offset)
+public void WriteAtOffset(double value, int offset)
+
+

Writes a value to the specified offset without advancing the pointer. Overloads exist for various data types including sbyte, byte, short, ushort, int, uint, long, ulong, float, double.

+

Seek

+
public void Seek(int offset)
+
+

Advances the stream by a specified number of bytes. offset is the number of bytes to advance by.

+

About the Offset Methods

+

The LittleEndianWriter struct provides several methods that operate on a specific offset without advancing the pointer.

+

While these methods do not significantly reduce the instruction count, they offer some minor performance advantages, +you can read more about this in About Section

+

Usage

+

Example usage of the LittleEndianWriter struct:

+
var writer = new LittleEndianWriter(ptr);
+
+writer.Write((int)12345);  // Write an int
+writer.Write((byte)65);    // Write a byte
+writer.WriteAtOffset((long)9876543210, 5);  // Write a long at offset 5 from current pointer
+
+ + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/Utilities/ArrayRental/index.html b/Utilities/ArrayRental/index.html new file mode 100644 index 0000000..1aa00d2 --- /dev/null +++ b/Utilities/ArrayRental/index.html @@ -0,0 +1,1040 @@ + + + + + + + + + + + + + + + + + + + + + + + + ArrayRental - Reloaded Memory Library + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

ArrayRental

+
+

ArrayRental is a struct that represents an instance of a rented array. It should be disposed of after use with the using statement.

+
+
+

If you need a generic version, use ArrayRental<T>.

+
+

The underlying array is managed by the shared ArrayPool.

+

Properties

+
    +
  • Array: The underlying array for this rental.
  • +
  • Span: Span for the underlying array. May be larger than requested length.
  • +
+

Constructor

+
public ArrayRental(int numBytes)
+
+

Rents a requested minimum number of bytes. Amount of data rented might be larger.

+

Slices

+

ArrayRentalSlice represents a slice of an ArrayRental. This API is meant to be used as a return value from methods, +and transfers ownership of the rental from the internal ArrayRental.

+
public ArrayRentalSlice(ArrayRental rental, int length)
+
+

Represents a slice of the array rental.

+

Usage

+

Rent an Array and Create a Slice

+
+

Make sure to dispose with using statement or explicit dispose.

+
+
// Will create a rental of at least 4096 bytes.
+using var rental = new ArrayRental(4096);
+
+

Rent an Array and Create a Slice

+
+

When you create an ArrayRentalSlice, the responsibility of disposing the rental is transferred to the slice. Make sure to not double dispose.

+
+
// Some Method
+ArrayRentalSlice CompressData(byte* data, int length) 
+{
+    var rental = new ArrayRental(numBytes);
+    // Compress into rental....
+    // And return a slice with just the info needed.
+    return new ArrayRentalSlice(rental, sliceLength);
+}
+
+// Method consumer
+using var compressed = CompressData(data, length);
+
+ + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/Utilities/Box/index.html b/Utilities/Box/index.html new file mode 100644 index 0000000..546f2b8 --- /dev/null +++ b/Utilities/Box/index.html @@ -0,0 +1,1176 @@ + + + + + + + + + + + + + + + + + + + + + + + + Box<T> - Reloaded Memory Library + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Box

+
+

Forked from Community Toolkit.

+
+
+

A class representing a boxed value type, providing build-time validation and automatic unboxing.

+
+

Box is a utility class that represents a boxed value type on the managed heap. It can be used in place of a non-generic object reference to a boxed value type, making the code more expressive and reducing the chances of errors.

+

Methods

+

GetFrom

+
public static Box<T> GetFrom(object obj)
+
+

Returns a Box<T> reference from the input object instance, representing a boxed T value.

+

DangerousGetFrom

+
public static Box<T> DangerousGetFrom(object obj)
+
+

Returns a Box<T> reference from the input object instance, representing a boxed T value. This method doesn't check the actual type of obj, so it is the responsibility of the caller to ensure it actually represents a boxed T value and not some other instance.

+

TryGetFrom

+
public static bool TryGetFrom(object obj, out Box<T>? box)
+
+

Tries to get a Box<T> reference from an input object representing a boxed T value. Returns true if a Box<T> instance was retrieved correctly, false otherwise.

+

Operators

+

implicit operator T

+
public static implicit operator T(Box<T> box)
+
+

Implicitly gets the T value from a given Box<T> instance.

+

implicit operator Box

+
public static implicit operator Box<T>(T value)
+
+

Implicitly creates a new Box<T> instance from a given T value.

+

Usage

+

Box and Unbox Value Type with Build-time Validation

+
Box<int> box = 42;
+int sum = box.Value + 1;
+
+

Retrieve a Mutable Reference to a Boxed Value

+
Box<MyStruct> box = new MyStruct { Field1 = 1, Field2 = 2 };
+ref MyStruct myStructRef = ref box.GetReference();
+myStructRef.Field1 = 3;
+
+

Extension Methods

+

GetReference

+
public static ref T GetReference<T>(this Box<T> box) where T : struct
+
+

Gets a T reference from a Box<T> instance.

+

Usage

+
Box<MyStruct> box = new MyStruct { Field1 = 1, Field2 = 2 };
+ref MyStruct myStructRef = ref box.GetReference();
+
+ + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/Utilities/CircularBuffer/index.html b/Utilities/CircularBuffer/index.html new file mode 100644 index 0000000..73151db --- /dev/null +++ b/Utilities/CircularBuffer/index.html @@ -0,0 +1,1136 @@ + + + + + + + + + + + + + + + + + + + + + + + + CircularBuffer - Reloaded Memory Library + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

CircularBuffer Class

+
+

The CircularBuffer is a writable buffer useful for temporary storage of data. It's a buffer whereby once you reach the end of the buffer, it loops back over to the beginning of the buffer, overwriting old elements.

+
+

Properties

+
    +
  • Start: The address of the CircularBuffer.
  • +
  • End: The address of the CircularBuffer.
  • +
  • Current: Address of the current item in the buffer.
  • +
  • Remaining: Remaining space in the buffer.
  • +
  • Size: The overall size of the buffer.
  • +
+

Constructors

+
    +
  • CircularBuffer(nuint start, int size): Creates a CircularBuffer within the target memory source.
  • +
+

Methods

+

Add

+
public nuint Add(byte* data, uint length)
+public nuint Add<TSource>(TSource source, byte* data, uint length)
+public nuint Add<TSource, T>(TSource source, T value)
+public nuint Add<T>(T value)
+
+

Adds a new item onto the circular buffer. Returns a pointer to the recently added item to the buffer, or zero if the item cannot fit.

+

CanItemFit

+
public ItemFit CanItemFit(uint itemSize)
+public ItemFit CanItemFit<T>()
+
+

Returns an enumerable describing if an item can fit into the buffer.

+

ItemFit Enum

+
+

Describes whether an item can fit into a given buffer.

+
+
    +
  • Yes: The item can fit into the buffer.
  • +
  • StartOfBuffer: The item can fit into the buffer, but not in the remaining space (will be placed at start of buffer).
  • +
  • No: The item is too large to fit into the buffer.
  • +
+

Examples

+

Adding an Integer to The Buffer

+
var circularBuffer = new CircularBuffer((nuint)bufferStartPtr, bufferSize);
+nuint pointerToValue = circularBuffer.Add(42);
+
+if (pointerToValue != UIntPtr.Zero)
+    Console.WriteLine("Value added successfully!");
+else
+    Console.WriteLine("Failed to add value to the buffer.");
+
+

Adding a Custom Struct to The Buffer

+
var circularBuffer = new CircularBuffer((nuint)bufferStart, bufferSize);
+var valueToAdd = new Vector2 { X = 1, Y = 2 };
+nuint pointerToValue = circularBuffer.Add(valueToAdd);
+
+if (pointerToValue != UIntPtr.Zero)
+    Console.WriteLine("Value added successfully!");
+else
+    Console.WriteLine("Failed to add value to the buffer.");
+
+

Checking if an item can fit in the buffer.

+
var circularBuffer = new CircularBuffer((nuint)bufferStart, bufferSize);
+var result = circularBuffer.CanItemFit<double>();
+
+switch (result)
+{
+    case CircularBuffer.ItemFit.Yes:
+        // "A double can fit in the buffer."
+        break;
+    case CircularBuffer.ItemFit.StartOfBuffer:
+        // "A double can fit in the buffer, but it will be placed at the start of the buffer."
+        break;
+    case CircularBuffer.ItemFit.No:
+        // "A double cannot fit in the buffer."
+        break;
+}
+
+ + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/Utilities/Endian/index.html b/Utilities/Endian/index.html new file mode 100644 index 0000000..393c8cf --- /dev/null +++ b/Utilities/Endian/index.html @@ -0,0 +1,1064 @@ + + + + + + + + + + + + + + + + + + + + + + + + Endian - Reloaded Memory Library + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Endian Class

+
+

The Endian class provides various utilities for converting primitives and structures between endians.

+
+

Methods

+

Reverse

+
public static byte Reverse(byte value)
+public static sbyte Reverse(sbyte value)
+public static short Reverse(short value)
+public static ushort Reverse(ushort value)
+public static int Reverse(int value)
+public static uint Reverse(uint value)
+public static long Reverse(long value)
+public static ulong Reverse(ulong value)
+public static float Reverse(float value)
+public static double Reverse(double value)
+
+

Reverses the byte order of the specified value.

+

Reverse (Generic)

+
+

Info

+

Utility method for structs with single values.

+
+
+

Warning

+

This method is provided for convenience.
+If the item size is not 1/2/4/8 bytes, this method will throw.

+
+
public static T Reverse<T>(T value) where T : unmanaged
+
+

Reverses the endian of a primitive value such as int, short, float, double etc.

+

Examples

+

Reversing an Integer's Endian

+
int value = 42;
+int reversedValue = Endian.Reverse(value);
+
+Console.WriteLine($"Original Value: {value}, Reversed Value: {reversedValue}");
+
+

This will print something like:

+
Original Value: 42, Reversed Value: 704643072
+
+

Reversing a Custom Struct's Endian

+
+

Warning

+

This will only work if the struct is a blittable type.

+
+
struct NamedOffset
+{
+    public int Offset;
+}
+
+MyStruct value = new NamedOffset { Offset = 1 };
+MyStruct reversedValue = Endian.Reverse(value);
+
+Console.WriteLine($"Original Value: {value.X}, Reversed Value: {reversedValue.X}");
+
+

This will print something like:

+
Original Value: 1 Reversed Value: 16777216
+
+ + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/Utilities/ObjectMarshal/index.html b/Utilities/ObjectMarshal/index.html new file mode 100644 index 0000000..6fadffe --- /dev/null +++ b/Utilities/ObjectMarshal/index.html @@ -0,0 +1,1111 @@ + + + + + + + + + + + + + + + + + + + + + + + + ObjectMarshal - Reloaded Memory Library + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

ObjectMarshal

+
+

Forked from Community Toolkit.

+
+
+

Utility class providing methods for working with object instances.

+
+

ObjectMarshal is a utility class that provides methods for calculating byte offsets to specific fields within objects, retrieving references to data within objects at specific offsets, and unboxing values from objects.

+

Methods

+

DangerousGetObjectDataByteOffset

+
public static IntPtr DangerousGetObjectDataByteOffset<T>(object obj, ref T data)
+
+

Calculates the byte offset to a specific field within a given object. The input parameters are not validated, and it's +the responsibility of the caller to ensure that the data reference is actually pointing to a memory location within obj.

+

DangerousGetObjectDataReferenceAt

+
public static ref T DangerousGetObjectDataReferenceAt<T>(object obj, IntPtr offset)
+
+

Gets a T reference to data within a given object at a specified offset. None of the input arguments is validated, and +it is the responsibility of the caller to ensure they are valid.

+

TryUnbox

+
public static bool TryUnbox<T>(this object obj, out T value) where T : struct
+
+

Tries to get a boxed T value from an input object instance. Returns true if a T value was retrieved correctly, +false otherwise.

+

DangerousUnbox

+
public static ref T DangerousUnbox<T>(object obj) where T : struct
+
+

Unboxes a T value from an input object instance. Throws an InvalidCastException when obj is not of type T.

+

Usage

+

Calculate Byte Offset

+
MyStruct myStruct = new MyStruct();
+ref int fieldRef = ref myStruct.SomeIntField;
+IntPtr offset = ObjectMarshal.DangerousGetObjectDataByteOffset(myStruct, ref fieldRef);
+
+

Get Reference At Specific Offset

+
MyStruct myStruct = new MyStruct();
+IntPtr fieldOffset = /* calculated offset */;
+ref int fieldRef = ref ObjectMarshal.DangerousGetObjectDataReferenceAt<MyStruct>(myStruct, fieldOffset);
+
+

Try to Unbox a value

+
object boxedInt = 42;
+int unboxedInt;
+
+if (boxedInt.TryUnbox(out unboxedInt))
+    Console.WriteLine($"Unboxed value: {unboxedInt}");
+
+

Unbox a value

+
object boxedInt = 42;
+ref int unboxedInt = ref ObjectMarshal.DangerousUnbox<int>(boxedInt);
+
+ + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/Utilities/Pinnable/index.html b/Utilities/Pinnable/index.html new file mode 100644 index 0000000..b7b8a8c --- /dev/null +++ b/Utilities/Pinnable/index.html @@ -0,0 +1,1033 @@ + + + + + + + + + + + + + + + + + + + + + + + + Pinnable<T> - Reloaded Memory Library + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Pinnable<T>

+
+

Allows you to pin an unmanaged object in a static location in memory, to be later accessible from native code.

+
+
+

Assume value is copied; modify the Pinnable instance to read/write values once created.

+
+

The Pinnable<T> class provides a way to pin native unmanaged objects in memory, ensuring that their memory addresses +remain constant during the lifetime of the Pinnable<T> instance. This can be useful when working with native +code that requires static memory addresses.

+

On newer runtimes, the memory is allocated into the Pinned Object Heap (POH); thus has no impact on effectiveness +of regular garbage collection.

+

Properties

+
    +
  • Value: The value pointed to by the Pointer. If the class was instantiated using an array, this is the first element of the array.
  • +
  • Pointer: Pointer to the native value in question. If the class was instantiated using an array, this is the pointer to the first element of the array.
  • +
+

Constructors

+
public Pinnable(T[] value);   // Pins an array of values to the heap.
+public Pinnable(in T value);     // Pins a single value to the heap.
+
+

Disposal

+

The Pinnable<T> class implements the IDisposable interface, which means you should dispose of the instance when you are done with it.

+

This can be done using the using statement, or by explicitly calling the Dispose() method.

+

Examples

+

Pinning a Single Value

+
int value = 42;
+
+using var pinnable = new Pinnable<int>(value);
+// Access the pinned value through pinnable.Value
+// Access the memory address of the pinned value through pinnable.Pointer
+
+

Pinning an Array

+
int[] array = new int[] { 1, 2, 3, 4, 5 };
+
+using var pinnable = new Pinnable<int>(value);
+// Access array element via `pinnable[x]`.
+// Access the first element of the pinned array through pinnable.Value
+// Access the memory address of the first element of the pinned array through pinnable.Pointer
+
+ + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/Utilities/TypeInfo/index.html b/Utilities/TypeInfo/index.html new file mode 100644 index 0000000..9dd3a92 --- /dev/null +++ b/Utilities/TypeInfo/index.html @@ -0,0 +1,1058 @@ + + + + + + + + + + + + + + + + + + + + + + TypeInfo - Reloaded Memory Library + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+ +
+ + + +
+
+ + + + + + + + +

TypeInfo

+
+

Utility class providing methods for obtaining information about different types.

+
+

Methods

+

ApproximateIsBlittable

+

public static bool ApproximateIsBlittable<T>()
+
+Returns true if a type is blittable, else false. This method uses an approximation, and may not work with generic types with blittable (unmanaged) constraints.

+

ApproximateIsBlittable

+

public static bool ApproximateIsBlittable(Type type)
+
+Returns true if a type is blittable, else false. This method uses an approximation, and may not work with generic types with blittable (unmanaged) constraints.

+

MarshalledSizeOf

+

public static int MarshalledSizeOf<T>()
+
+Returns size of item after marshalling is performed. This caches the value, thus is faster to access.

+

Usage

+

Check if a Type is Blittable (Generic)

+
bool isBlittable = TypeInfo.ApproximateIsBlittable<int>();
+
+

Check if a Type is Blittable (Non-Generic)

+
bool isBlittable = TypeInfo.ApproximateIsBlittable(typeof(int));
+
+

Check size of Type After Marshalling

+
int size = TypeInfo.MarshalledSizeOf<int>();
+
+ + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/assets/images/favicon.png b/assets/images/favicon.png new file mode 100644 index 0000000..1cf13b9 Binary files /dev/null and b/assets/images/favicon.png differ diff --git a/assets/javascripts/bundle.51d95adb.min.js b/assets/javascripts/bundle.51d95adb.min.js new file mode 100644 index 0000000..b20ec68 --- /dev/null +++ b/assets/javascripts/bundle.51d95adb.min.js @@ -0,0 +1,29 @@ +"use strict";(()=>{var Hi=Object.create;var xr=Object.defineProperty;var Pi=Object.getOwnPropertyDescriptor;var $i=Object.getOwnPropertyNames,kt=Object.getOwnPropertySymbols,Ii=Object.getPrototypeOf,Er=Object.prototype.hasOwnProperty,an=Object.prototype.propertyIsEnumerable;var on=(e,t,r)=>t in e?xr(e,t,{enumerable:!0,configurable:!0,writable:!0,value:r}):e[t]=r,P=(e,t)=>{for(var r in t||(t={}))Er.call(t,r)&&on(e,r,t[r]);if(kt)for(var r of kt(t))an.call(t,r)&&on(e,r,t[r]);return e};var sn=(e,t)=>{var r={};for(var n in e)Er.call(e,n)&&t.indexOf(n)<0&&(r[n]=e[n]);if(e!=null&&kt)for(var n of kt(e))t.indexOf(n)<0&&an.call(e,n)&&(r[n]=e[n]);return r};var Ht=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports);var Fi=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of $i(t))!Er.call(e,o)&&o!==r&&xr(e,o,{get:()=>t[o],enumerable:!(n=Pi(t,o))||n.enumerable});return e};var yt=(e,t,r)=>(r=e!=null?Hi(Ii(e)):{},Fi(t||!e||!e.__esModule?xr(r,"default",{value:e,enumerable:!0}):r,e));var fn=Ht((wr,cn)=>{(function(e,t){typeof wr=="object"&&typeof cn!="undefined"?t():typeof define=="function"&&define.amd?define(t):t()})(wr,function(){"use strict";function e(r){var n=!0,o=!1,i=null,a={text:!0,search:!0,url:!0,tel:!0,email:!0,password:!0,number:!0,date:!0,month:!0,week:!0,time:!0,datetime:!0,"datetime-local":!0};function s(T){return!!(T&&T!==document&&T.nodeName!=="HTML"&&T.nodeName!=="BODY"&&"classList"in T&&"contains"in T.classList)}function f(T){var Ke=T.type,We=T.tagName;return!!(We==="INPUT"&&a[Ke]&&!T.readOnly||We==="TEXTAREA"&&!T.readOnly||T.isContentEditable)}function c(T){T.classList.contains("focus-visible")||(T.classList.add("focus-visible"),T.setAttribute("data-focus-visible-added",""))}function u(T){T.hasAttribute("data-focus-visible-added")&&(T.classList.remove("focus-visible"),T.removeAttribute("data-focus-visible-added"))}function p(T){T.metaKey||T.altKey||T.ctrlKey||(s(r.activeElement)&&c(r.activeElement),n=!0)}function m(T){n=!1}function d(T){s(T.target)&&(n||f(T.target))&&c(T.target)}function h(T){s(T.target)&&(T.target.classList.contains("focus-visible")||T.target.hasAttribute("data-focus-visible-added"))&&(o=!0,window.clearTimeout(i),i=window.setTimeout(function(){o=!1},100),u(T.target))}function v(T){document.visibilityState==="hidden"&&(o&&(n=!0),B())}function B(){document.addEventListener("mousemove",z),document.addEventListener("mousedown",z),document.addEventListener("mouseup",z),document.addEventListener("pointermove",z),document.addEventListener("pointerdown",z),document.addEventListener("pointerup",z),document.addEventListener("touchmove",z),document.addEventListener("touchstart",z),document.addEventListener("touchend",z)}function re(){document.removeEventListener("mousemove",z),document.removeEventListener("mousedown",z),document.removeEventListener("mouseup",z),document.removeEventListener("pointermove",z),document.removeEventListener("pointerdown",z),document.removeEventListener("pointerup",z),document.removeEventListener("touchmove",z),document.removeEventListener("touchstart",z),document.removeEventListener("touchend",z)}function z(T){T.target.nodeName&&T.target.nodeName.toLowerCase()==="html"||(n=!1,re())}document.addEventListener("keydown",p,!0),document.addEventListener("mousedown",m,!0),document.addEventListener("pointerdown",m,!0),document.addEventListener("touchstart",m,!0),document.addEventListener("visibilitychange",v,!0),B(),r.addEventListener("focus",d,!0),r.addEventListener("blur",h,!0),r.nodeType===Node.DOCUMENT_FRAGMENT_NODE&&r.host?r.host.setAttribute("data-js-focus-visible",""):r.nodeType===Node.DOCUMENT_NODE&&(document.documentElement.classList.add("js-focus-visible"),document.documentElement.setAttribute("data-js-focus-visible",""))}if(typeof window!="undefined"&&typeof document!="undefined"){window.applyFocusVisiblePolyfill=e;var t;try{t=new CustomEvent("focus-visible-polyfill-ready")}catch(r){t=document.createEvent("CustomEvent"),t.initCustomEvent("focus-visible-polyfill-ready",!1,!1,{})}window.dispatchEvent(t)}typeof document!="undefined"&&e(document)})});var un=Ht(Sr=>{(function(e){var t=function(){try{return!!Symbol.iterator}catch(c){return!1}},r=t(),n=function(c){var u={next:function(){var p=c.shift();return{done:p===void 0,value:p}}};return r&&(u[Symbol.iterator]=function(){return u}),u},o=function(c){return encodeURIComponent(c).replace(/%20/g,"+")},i=function(c){return decodeURIComponent(String(c).replace(/\+/g," "))},a=function(){var c=function(p){Object.defineProperty(this,"_entries",{writable:!0,value:{}});var m=typeof p;if(m!=="undefined")if(m==="string")p!==""&&this._fromString(p);else if(p instanceof c){var d=this;p.forEach(function(re,z){d.append(z,re)})}else if(p!==null&&m==="object")if(Object.prototype.toString.call(p)==="[object Array]")for(var h=0;hd[0]?1:0}),c._entries&&(c._entries={});for(var p=0;p1?i(d[1]):"")}})})(typeof global!="undefined"?global:typeof window!="undefined"?window:typeof self!="undefined"?self:Sr);(function(e){var t=function(){try{var o=new e.URL("b","http://a");return o.pathname="c d",o.href==="http://a/c%20d"&&o.searchParams}catch(i){return!1}},r=function(){var o=e.URL,i=function(f,c){typeof f!="string"&&(f=String(f)),c&&typeof c!="string"&&(c=String(c));var u=document,p;if(c&&(e.location===void 0||c!==e.location.href)){c=c.toLowerCase(),u=document.implementation.createHTMLDocument(""),p=u.createElement("base"),p.href=c,u.head.appendChild(p);try{if(p.href.indexOf(c)!==0)throw new Error(p.href)}catch(T){throw new Error("URL unable to set base "+c+" due to "+T)}}var m=u.createElement("a");m.href=f,p&&(u.body.appendChild(m),m.href=m.href);var d=u.createElement("input");if(d.type="url",d.value=f,m.protocol===":"||!/:/.test(m.href)||!d.checkValidity()&&!c)throw new TypeError("Invalid URL");Object.defineProperty(this,"_anchorElement",{value:m});var h=new e.URLSearchParams(this.search),v=!0,B=!0,re=this;["append","delete","set"].forEach(function(T){var Ke=h[T];h[T]=function(){Ke.apply(h,arguments),v&&(B=!1,re.search=h.toString(),B=!0)}}),Object.defineProperty(this,"searchParams",{value:h,enumerable:!0});var z=void 0;Object.defineProperty(this,"_updateSearchParams",{enumerable:!1,configurable:!1,writable:!1,value:function(){this.search!==z&&(z=this.search,B&&(v=!1,this.searchParams._fromString(this.search),v=!0))}})},a=i.prototype,s=function(f){Object.defineProperty(a,f,{get:function(){return this._anchorElement[f]},set:function(c){this._anchorElement[f]=c},enumerable:!0})};["hash","host","hostname","port","protocol"].forEach(function(f){s(f)}),Object.defineProperty(a,"search",{get:function(){return this._anchorElement.search},set:function(f){this._anchorElement.search=f,this._updateSearchParams()},enumerable:!0}),Object.defineProperties(a,{toString:{get:function(){var f=this;return function(){return f.href}}},href:{get:function(){return this._anchorElement.href.replace(/\?$/,"")},set:function(f){this._anchorElement.href=f,this._updateSearchParams()},enumerable:!0},pathname:{get:function(){return this._anchorElement.pathname.replace(/(^\/?)/,"/")},set:function(f){this._anchorElement.pathname=f},enumerable:!0},origin:{get:function(){var f={"http:":80,"https:":443,"ftp:":21}[this._anchorElement.protocol],c=this._anchorElement.port!=f&&this._anchorElement.port!=="";return this._anchorElement.protocol+"//"+this._anchorElement.hostname+(c?":"+this._anchorElement.port:"")},enumerable:!0},password:{get:function(){return""},set:function(f){},enumerable:!0},username:{get:function(){return""},set:function(f){},enumerable:!0}}),i.createObjectURL=function(f){return o.createObjectURL.apply(o,arguments)},i.revokeObjectURL=function(f){return o.revokeObjectURL.apply(o,arguments)},e.URL=i};if(t()||r(),e.location!==void 0&&!("origin"in e.location)){var n=function(){return e.location.protocol+"//"+e.location.hostname+(e.location.port?":"+e.location.port:"")};try{Object.defineProperty(e.location,"origin",{get:n,enumerable:!0})}catch(o){setInterval(function(){e.location.origin=n()},100)}}})(typeof global!="undefined"?global:typeof window!="undefined"?window:typeof self!="undefined"?self:Sr)});var Qr=Ht((Lt,Kr)=>{/*! + * clipboard.js v2.0.11 + * https://clipboardjs.com/ + * + * Licensed MIT © Zeno Rocha + */(function(t,r){typeof Lt=="object"&&typeof Kr=="object"?Kr.exports=r():typeof define=="function"&&define.amd?define([],r):typeof Lt=="object"?Lt.ClipboardJS=r():t.ClipboardJS=r()})(Lt,function(){return function(){var e={686:function(n,o,i){"use strict";i.d(o,{default:function(){return ki}});var a=i(279),s=i.n(a),f=i(370),c=i.n(f),u=i(817),p=i.n(u);function m(j){try{return document.execCommand(j)}catch(O){return!1}}var d=function(O){var w=p()(O);return m("cut"),w},h=d;function v(j){var O=document.documentElement.getAttribute("dir")==="rtl",w=document.createElement("textarea");w.style.fontSize="12pt",w.style.border="0",w.style.padding="0",w.style.margin="0",w.style.position="absolute",w.style[O?"right":"left"]="-9999px";var k=window.pageYOffset||document.documentElement.scrollTop;return w.style.top="".concat(k,"px"),w.setAttribute("readonly",""),w.value=j,w}var B=function(O,w){var k=v(O);w.container.appendChild(k);var F=p()(k);return m("copy"),k.remove(),F},re=function(O){var w=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{container:document.body},k="";return typeof O=="string"?k=B(O,w):O instanceof HTMLInputElement&&!["text","search","url","tel","password"].includes(O==null?void 0:O.type)?k=B(O.value,w):(k=p()(O),m("copy")),k},z=re;function T(j){return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?T=function(w){return typeof w}:T=function(w){return w&&typeof Symbol=="function"&&w.constructor===Symbol&&w!==Symbol.prototype?"symbol":typeof w},T(j)}var Ke=function(){var O=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},w=O.action,k=w===void 0?"copy":w,F=O.container,q=O.target,Le=O.text;if(k!=="copy"&&k!=="cut")throw new Error('Invalid "action" value, use either "copy" or "cut"');if(q!==void 0)if(q&&T(q)==="object"&&q.nodeType===1){if(k==="copy"&&q.hasAttribute("disabled"))throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');if(k==="cut"&&(q.hasAttribute("readonly")||q.hasAttribute("disabled")))throw new Error(`Invalid "target" attribute. You can't cut text from elements with "readonly" or "disabled" attributes`)}else throw new Error('Invalid "target" value, use a valid Element');if(Le)return z(Le,{container:F});if(q)return k==="cut"?h(q):z(q,{container:F})},We=Ke;function Ie(j){return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?Ie=function(w){return typeof w}:Ie=function(w){return w&&typeof Symbol=="function"&&w.constructor===Symbol&&w!==Symbol.prototype?"symbol":typeof w},Ie(j)}function Ti(j,O){if(!(j instanceof O))throw new TypeError("Cannot call a class as a function")}function nn(j,O){for(var w=0;w0&&arguments[0]!==void 0?arguments[0]:{};this.action=typeof F.action=="function"?F.action:this.defaultAction,this.target=typeof F.target=="function"?F.target:this.defaultTarget,this.text=typeof F.text=="function"?F.text:this.defaultText,this.container=Ie(F.container)==="object"?F.container:document.body}},{key:"listenClick",value:function(F){var q=this;this.listener=c()(F,"click",function(Le){return q.onClick(Le)})}},{key:"onClick",value:function(F){var q=F.delegateTarget||F.currentTarget,Le=this.action(q)||"copy",Rt=We({action:Le,container:this.container,target:this.target(q),text:this.text(q)});this.emit(Rt?"success":"error",{action:Le,text:Rt,trigger:q,clearSelection:function(){q&&q.focus(),window.getSelection().removeAllRanges()}})}},{key:"defaultAction",value:function(F){return yr("action",F)}},{key:"defaultTarget",value:function(F){var q=yr("target",F);if(q)return document.querySelector(q)}},{key:"defaultText",value:function(F){return yr("text",F)}},{key:"destroy",value:function(){this.listener.destroy()}}],[{key:"copy",value:function(F){var q=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{container:document.body};return z(F,q)}},{key:"cut",value:function(F){return h(F)}},{key:"isSupported",value:function(){var F=arguments.length>0&&arguments[0]!==void 0?arguments[0]:["copy","cut"],q=typeof F=="string"?[F]:F,Le=!!document.queryCommandSupported;return q.forEach(function(Rt){Le=Le&&!!document.queryCommandSupported(Rt)}),Le}}]),w}(s()),ki=Ri},828:function(n){var o=9;if(typeof Element!="undefined"&&!Element.prototype.matches){var i=Element.prototype;i.matches=i.matchesSelector||i.mozMatchesSelector||i.msMatchesSelector||i.oMatchesSelector||i.webkitMatchesSelector}function a(s,f){for(;s&&s.nodeType!==o;){if(typeof s.matches=="function"&&s.matches(f))return s;s=s.parentNode}}n.exports=a},438:function(n,o,i){var a=i(828);function s(u,p,m,d,h){var v=c.apply(this,arguments);return u.addEventListener(m,v,h),{destroy:function(){u.removeEventListener(m,v,h)}}}function f(u,p,m,d,h){return typeof u.addEventListener=="function"?s.apply(null,arguments):typeof m=="function"?s.bind(null,document).apply(null,arguments):(typeof u=="string"&&(u=document.querySelectorAll(u)),Array.prototype.map.call(u,function(v){return s(v,p,m,d,h)}))}function c(u,p,m,d){return function(h){h.delegateTarget=a(h.target,p),h.delegateTarget&&d.call(u,h)}}n.exports=f},879:function(n,o){o.node=function(i){return i!==void 0&&i instanceof HTMLElement&&i.nodeType===1},o.nodeList=function(i){var a=Object.prototype.toString.call(i);return i!==void 0&&(a==="[object NodeList]"||a==="[object HTMLCollection]")&&"length"in i&&(i.length===0||o.node(i[0]))},o.string=function(i){return typeof i=="string"||i instanceof String},o.fn=function(i){var a=Object.prototype.toString.call(i);return a==="[object Function]"}},370:function(n,o,i){var a=i(879),s=i(438);function f(m,d,h){if(!m&&!d&&!h)throw new Error("Missing required arguments");if(!a.string(d))throw new TypeError("Second argument must be a String");if(!a.fn(h))throw new TypeError("Third argument must be a Function");if(a.node(m))return c(m,d,h);if(a.nodeList(m))return u(m,d,h);if(a.string(m))return p(m,d,h);throw new TypeError("First argument must be a String, HTMLElement, HTMLCollection, or NodeList")}function c(m,d,h){return m.addEventListener(d,h),{destroy:function(){m.removeEventListener(d,h)}}}function u(m,d,h){return Array.prototype.forEach.call(m,function(v){v.addEventListener(d,h)}),{destroy:function(){Array.prototype.forEach.call(m,function(v){v.removeEventListener(d,h)})}}}function p(m,d,h){return s(document.body,m,d,h)}n.exports=f},817:function(n){function o(i){var a;if(i.nodeName==="SELECT")i.focus(),a=i.value;else if(i.nodeName==="INPUT"||i.nodeName==="TEXTAREA"){var s=i.hasAttribute("readonly");s||i.setAttribute("readonly",""),i.select(),i.setSelectionRange(0,i.value.length),s||i.removeAttribute("readonly"),a=i.value}else{i.hasAttribute("contenteditable")&&i.focus();var f=window.getSelection(),c=document.createRange();c.selectNodeContents(i),f.removeAllRanges(),f.addRange(c),a=f.toString()}return a}n.exports=o},279:function(n){function o(){}o.prototype={on:function(i,a,s){var f=this.e||(this.e={});return(f[i]||(f[i]=[])).push({fn:a,ctx:s}),this},once:function(i,a,s){var f=this;function c(){f.off(i,c),a.apply(s,arguments)}return c._=a,this.on(i,c,s)},emit:function(i){var a=[].slice.call(arguments,1),s=((this.e||(this.e={}))[i]||[]).slice(),f=0,c=s.length;for(f;f{"use strict";/*! + * escape-html + * Copyright(c) 2012-2013 TJ Holowaychuk + * Copyright(c) 2015 Andreas Lubbe + * Copyright(c) 2015 Tiancheng "Timothy" Gu + * MIT Licensed + */var is=/["'&<>]/;Jo.exports=as;function as(e){var t=""+e,r=is.exec(t);if(!r)return t;var n,o="",i=0,a=0;for(i=r.index;i0&&i[i.length-1])&&(c[0]===6||c[0]===2)){r=0;continue}if(c[0]===3&&(!i||c[1]>i[0]&&c[1]=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")}function W(e,t){var r=typeof Symbol=="function"&&e[Symbol.iterator];if(!r)return e;var n=r.call(e),o,i=[],a;try{for(;(t===void 0||t-- >0)&&!(o=n.next()).done;)i.push(o.value)}catch(s){a={error:s}}finally{try{o&&!o.done&&(r=n.return)&&r.call(n)}finally{if(a)throw a.error}}return i}function D(e,t,r){if(r||arguments.length===2)for(var n=0,o=t.length,i;n1||s(m,d)})})}function s(m,d){try{f(n[m](d))}catch(h){p(i[0][3],h)}}function f(m){m.value instanceof Xe?Promise.resolve(m.value.v).then(c,u):p(i[0][2],m)}function c(m){s("next",m)}function u(m){s("throw",m)}function p(m,d){m(d),i.shift(),i.length&&s(i[0][0],i[0][1])}}function mn(e){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var t=e[Symbol.asyncIterator],r;return t?t.call(e):(e=typeof xe=="function"?xe(e):e[Symbol.iterator](),r={},n("next"),n("throw"),n("return"),r[Symbol.asyncIterator]=function(){return this},r);function n(i){r[i]=e[i]&&function(a){return new Promise(function(s,f){a=e[i](a),o(s,f,a.done,a.value)})}}function o(i,a,s,f){Promise.resolve(f).then(function(c){i({value:c,done:s})},a)}}function A(e){return typeof e=="function"}function at(e){var t=function(n){Error.call(n),n.stack=new Error().stack},r=e(t);return r.prototype=Object.create(Error.prototype),r.prototype.constructor=r,r}var $t=at(function(e){return function(r){e(this),this.message=r?r.length+` errors occurred during unsubscription: +`+r.map(function(n,o){return o+1+") "+n.toString()}).join(` + `):"",this.name="UnsubscriptionError",this.errors=r}});function De(e,t){if(e){var r=e.indexOf(t);0<=r&&e.splice(r,1)}}var Fe=function(){function e(t){this.initialTeardown=t,this.closed=!1,this._parentage=null,this._finalizers=null}return e.prototype.unsubscribe=function(){var t,r,n,o,i;if(!this.closed){this.closed=!0;var a=this._parentage;if(a)if(this._parentage=null,Array.isArray(a))try{for(var s=xe(a),f=s.next();!f.done;f=s.next()){var c=f.value;c.remove(this)}}catch(v){t={error:v}}finally{try{f&&!f.done&&(r=s.return)&&r.call(s)}finally{if(t)throw t.error}}else a.remove(this);var u=this.initialTeardown;if(A(u))try{u()}catch(v){i=v instanceof $t?v.errors:[v]}var p=this._finalizers;if(p){this._finalizers=null;try{for(var m=xe(p),d=m.next();!d.done;d=m.next()){var h=d.value;try{dn(h)}catch(v){i=i!=null?i:[],v instanceof $t?i=D(D([],W(i)),W(v.errors)):i.push(v)}}}catch(v){n={error:v}}finally{try{d&&!d.done&&(o=m.return)&&o.call(m)}finally{if(n)throw n.error}}}if(i)throw new $t(i)}},e.prototype.add=function(t){var r;if(t&&t!==this)if(this.closed)dn(t);else{if(t instanceof e){if(t.closed||t._hasParent(this))return;t._addParent(this)}(this._finalizers=(r=this._finalizers)!==null&&r!==void 0?r:[]).push(t)}},e.prototype._hasParent=function(t){var r=this._parentage;return r===t||Array.isArray(r)&&r.includes(t)},e.prototype._addParent=function(t){var r=this._parentage;this._parentage=Array.isArray(r)?(r.push(t),r):r?[r,t]:t},e.prototype._removeParent=function(t){var r=this._parentage;r===t?this._parentage=null:Array.isArray(r)&&De(r,t)},e.prototype.remove=function(t){var r=this._finalizers;r&&De(r,t),t instanceof e&&t._removeParent(this)},e.EMPTY=function(){var t=new e;return t.closed=!0,t}(),e}();var Or=Fe.EMPTY;function It(e){return e instanceof Fe||e&&"closed"in e&&A(e.remove)&&A(e.add)&&A(e.unsubscribe)}function dn(e){A(e)?e():e.unsubscribe()}var Ae={onUnhandledError:null,onStoppedNotification:null,Promise:void 0,useDeprecatedSynchronousErrorHandling:!1,useDeprecatedNextContext:!1};var st={setTimeout:function(e,t){for(var r=[],n=2;n0},enumerable:!1,configurable:!0}),t.prototype._trySubscribe=function(r){return this._throwIfClosed(),e.prototype._trySubscribe.call(this,r)},t.prototype._subscribe=function(r){return this._throwIfClosed(),this._checkFinalizedStatuses(r),this._innerSubscribe(r)},t.prototype._innerSubscribe=function(r){var n=this,o=this,i=o.hasError,a=o.isStopped,s=o.observers;return i||a?Or:(this.currentObservers=null,s.push(r),new Fe(function(){n.currentObservers=null,De(s,r)}))},t.prototype._checkFinalizedStatuses=function(r){var n=this,o=n.hasError,i=n.thrownError,a=n.isStopped;o?r.error(i):a&&r.complete()},t.prototype.asObservable=function(){var r=new U;return r.source=this,r},t.create=function(r,n){return new wn(r,n)},t}(U);var wn=function(e){ne(t,e);function t(r,n){var o=e.call(this)||this;return o.destination=r,o.source=n,o}return t.prototype.next=function(r){var n,o;(o=(n=this.destination)===null||n===void 0?void 0:n.next)===null||o===void 0||o.call(n,r)},t.prototype.error=function(r){var n,o;(o=(n=this.destination)===null||n===void 0?void 0:n.error)===null||o===void 0||o.call(n,r)},t.prototype.complete=function(){var r,n;(n=(r=this.destination)===null||r===void 0?void 0:r.complete)===null||n===void 0||n.call(r)},t.prototype._subscribe=function(r){var n,o;return(o=(n=this.source)===null||n===void 0?void 0:n.subscribe(r))!==null&&o!==void 0?o:Or},t}(E);var Et={now:function(){return(Et.delegate||Date).now()},delegate:void 0};var wt=function(e){ne(t,e);function t(r,n,o){r===void 0&&(r=1/0),n===void 0&&(n=1/0),o===void 0&&(o=Et);var i=e.call(this)||this;return i._bufferSize=r,i._windowTime=n,i._timestampProvider=o,i._buffer=[],i._infiniteTimeWindow=!0,i._infiniteTimeWindow=n===1/0,i._bufferSize=Math.max(1,r),i._windowTime=Math.max(1,n),i}return t.prototype.next=function(r){var n=this,o=n.isStopped,i=n._buffer,a=n._infiniteTimeWindow,s=n._timestampProvider,f=n._windowTime;o||(i.push(r),!a&&i.push(s.now()+f)),this._trimBuffer(),e.prototype.next.call(this,r)},t.prototype._subscribe=function(r){this._throwIfClosed(),this._trimBuffer();for(var n=this._innerSubscribe(r),o=this,i=o._infiniteTimeWindow,a=o._buffer,s=a.slice(),f=0;f0?e.prototype.requestAsyncId.call(this,r,n,o):(r.actions.push(this),r._scheduled||(r._scheduled=ut.requestAnimationFrame(function(){return r.flush(void 0)})))},t.prototype.recycleAsyncId=function(r,n,o){var i;if(o===void 0&&(o=0),o!=null?o>0:this.delay>0)return e.prototype.recycleAsyncId.call(this,r,n,o);var a=r.actions;n!=null&&((i=a[a.length-1])===null||i===void 0?void 0:i.id)!==n&&(ut.cancelAnimationFrame(n),r._scheduled=void 0)},t}(Ut);var On=function(e){ne(t,e);function t(){return e!==null&&e.apply(this,arguments)||this}return t.prototype.flush=function(r){this._active=!0;var n=this._scheduled;this._scheduled=void 0;var o=this.actions,i;r=r||o.shift();do if(i=r.execute(r.state,r.delay))break;while((r=o[0])&&r.id===n&&o.shift());if(this._active=!1,i){for(;(r=o[0])&&r.id===n&&o.shift();)r.unsubscribe();throw i}},t}(Wt);var we=new On(Tn);var R=new U(function(e){return e.complete()});function Dt(e){return e&&A(e.schedule)}function kr(e){return e[e.length-1]}function Qe(e){return A(kr(e))?e.pop():void 0}function Se(e){return Dt(kr(e))?e.pop():void 0}function Vt(e,t){return typeof kr(e)=="number"?e.pop():t}var pt=function(e){return e&&typeof e.length=="number"&&typeof e!="function"};function zt(e){return A(e==null?void 0:e.then)}function Nt(e){return A(e[ft])}function qt(e){return Symbol.asyncIterator&&A(e==null?void 0:e[Symbol.asyncIterator])}function Kt(e){return new TypeError("You provided "+(e!==null&&typeof e=="object"?"an invalid object":"'"+e+"'")+" where a stream was expected. You can provide an Observable, Promise, ReadableStream, Array, AsyncIterable, or Iterable.")}function Ki(){return typeof Symbol!="function"||!Symbol.iterator?"@@iterator":Symbol.iterator}var Qt=Ki();function Yt(e){return A(e==null?void 0:e[Qt])}function Gt(e){return ln(this,arguments,function(){var r,n,o,i;return Pt(this,function(a){switch(a.label){case 0:r=e.getReader(),a.label=1;case 1:a.trys.push([1,,9,10]),a.label=2;case 2:return[4,Xe(r.read())];case 3:return n=a.sent(),o=n.value,i=n.done,i?[4,Xe(void 0)]:[3,5];case 4:return[2,a.sent()];case 5:return[4,Xe(o)];case 6:return[4,a.sent()];case 7:return a.sent(),[3,2];case 8:return[3,10];case 9:return r.releaseLock(),[7];case 10:return[2]}})})}function Bt(e){return A(e==null?void 0:e.getReader)}function $(e){if(e instanceof U)return e;if(e!=null){if(Nt(e))return Qi(e);if(pt(e))return Yi(e);if(zt(e))return Gi(e);if(qt(e))return _n(e);if(Yt(e))return Bi(e);if(Bt(e))return Ji(e)}throw Kt(e)}function Qi(e){return new U(function(t){var r=e[ft]();if(A(r.subscribe))return r.subscribe(t);throw new TypeError("Provided object does not correctly implement Symbol.observable")})}function Yi(e){return new U(function(t){for(var r=0;r=2;return function(n){return n.pipe(e?_(function(o,i){return e(o,i,n)}):me,Oe(1),r?He(t):zn(function(){return new Xt}))}}function Nn(){for(var e=[],t=0;t=2,!0))}function fe(e){e===void 0&&(e={});var t=e.connector,r=t===void 0?function(){return new E}:t,n=e.resetOnError,o=n===void 0?!0:n,i=e.resetOnComplete,a=i===void 0?!0:i,s=e.resetOnRefCountZero,f=s===void 0?!0:s;return function(c){var u,p,m,d=0,h=!1,v=!1,B=function(){p==null||p.unsubscribe(),p=void 0},re=function(){B(),u=m=void 0,h=v=!1},z=function(){var T=u;re(),T==null||T.unsubscribe()};return g(function(T,Ke){d++,!v&&!h&&B();var We=m=m!=null?m:r();Ke.add(function(){d--,d===0&&!v&&!h&&(p=jr(z,f))}),We.subscribe(Ke),!u&&d>0&&(u=new et({next:function(Ie){return We.next(Ie)},error:function(Ie){v=!0,B(),p=jr(re,o,Ie),We.error(Ie)},complete:function(){h=!0,B(),p=jr(re,a),We.complete()}}),$(T).subscribe(u))})(c)}}function jr(e,t){for(var r=[],n=2;ne.next(document)),e}function K(e,t=document){return Array.from(t.querySelectorAll(e))}function V(e,t=document){let r=se(e,t);if(typeof r=="undefined")throw new ReferenceError(`Missing element: expected "${e}" to be present`);return r}function se(e,t=document){return t.querySelector(e)||void 0}function _e(){return document.activeElement instanceof HTMLElement&&document.activeElement||void 0}function tr(e){return L(b(document.body,"focusin"),b(document.body,"focusout")).pipe(ke(1),l(()=>{let t=_e();return typeof t!="undefined"?e.contains(t):!1}),N(e===_e()),Y())}function Be(e){return{x:e.offsetLeft,y:e.offsetTop}}function Yn(e){return L(b(window,"load"),b(window,"resize")).pipe(Ce(0,we),l(()=>Be(e)),N(Be(e)))}function rr(e){return{x:e.scrollLeft,y:e.scrollTop}}function dt(e){return L(b(e,"scroll"),b(window,"resize")).pipe(Ce(0,we),l(()=>rr(e)),N(rr(e)))}var Bn=function(){if(typeof Map!="undefined")return Map;function e(t,r){var n=-1;return t.some(function(o,i){return o[0]===r?(n=i,!0):!1}),n}return function(){function t(){this.__entries__=[]}return Object.defineProperty(t.prototype,"size",{get:function(){return this.__entries__.length},enumerable:!0,configurable:!0}),t.prototype.get=function(r){var n=e(this.__entries__,r),o=this.__entries__[n];return o&&o[1]},t.prototype.set=function(r,n){var o=e(this.__entries__,r);~o?this.__entries__[o][1]=n:this.__entries__.push([r,n])},t.prototype.delete=function(r){var n=this.__entries__,o=e(n,r);~o&&n.splice(o,1)},t.prototype.has=function(r){return!!~e(this.__entries__,r)},t.prototype.clear=function(){this.__entries__.splice(0)},t.prototype.forEach=function(r,n){n===void 0&&(n=null);for(var o=0,i=this.__entries__;o0},e.prototype.connect_=function(){!zr||this.connected_||(document.addEventListener("transitionend",this.onTransitionEnd_),window.addEventListener("resize",this.refresh),xa?(this.mutationsObserver_=new MutationObserver(this.refresh),this.mutationsObserver_.observe(document,{attributes:!0,childList:!0,characterData:!0,subtree:!0})):(document.addEventListener("DOMSubtreeModified",this.refresh),this.mutationEventsAdded_=!0),this.connected_=!0)},e.prototype.disconnect_=function(){!zr||!this.connected_||(document.removeEventListener("transitionend",this.onTransitionEnd_),window.removeEventListener("resize",this.refresh),this.mutationsObserver_&&this.mutationsObserver_.disconnect(),this.mutationEventsAdded_&&document.removeEventListener("DOMSubtreeModified",this.refresh),this.mutationsObserver_=null,this.mutationEventsAdded_=!1,this.connected_=!1)},e.prototype.onTransitionEnd_=function(t){var r=t.propertyName,n=r===void 0?"":r,o=ya.some(function(i){return!!~n.indexOf(i)});o&&this.refresh()},e.getInstance=function(){return this.instance_||(this.instance_=new e),this.instance_},e.instance_=null,e}(),Jn=function(e,t){for(var r=0,n=Object.keys(t);r0},e}(),Zn=typeof WeakMap!="undefined"?new WeakMap:new Bn,eo=function(){function e(t){if(!(this instanceof e))throw new TypeError("Cannot call a class as a function.");if(!arguments.length)throw new TypeError("1 argument required, but only 0 present.");var r=Ea.getInstance(),n=new Ra(t,r,this);Zn.set(this,n)}return e}();["observe","unobserve","disconnect"].forEach(function(e){eo.prototype[e]=function(){var t;return(t=Zn.get(this))[e].apply(t,arguments)}});var ka=function(){return typeof nr.ResizeObserver!="undefined"?nr.ResizeObserver:eo}(),to=ka;var ro=new E,Ha=I(()=>H(new to(e=>{for(let t of e)ro.next(t)}))).pipe(x(e=>L(Te,H(e)).pipe(C(()=>e.disconnect()))),J(1));function de(e){return{width:e.offsetWidth,height:e.offsetHeight}}function ge(e){return Ha.pipe(S(t=>t.observe(e)),x(t=>ro.pipe(_(({target:r})=>r===e),C(()=>t.unobserve(e)),l(()=>de(e)))),N(de(e)))}function bt(e){return{width:e.scrollWidth,height:e.scrollHeight}}function ar(e){let t=e.parentElement;for(;t&&(e.scrollWidth<=t.scrollWidth&&e.scrollHeight<=t.scrollHeight);)t=(e=t).parentElement;return t?e:void 0}var no=new E,Pa=I(()=>H(new IntersectionObserver(e=>{for(let t of e)no.next(t)},{threshold:0}))).pipe(x(e=>L(Te,H(e)).pipe(C(()=>e.disconnect()))),J(1));function sr(e){return Pa.pipe(S(t=>t.observe(e)),x(t=>no.pipe(_(({target:r})=>r===e),C(()=>t.unobserve(e)),l(({isIntersecting:r})=>r))))}function oo(e,t=16){return dt(e).pipe(l(({y:r})=>{let n=de(e),o=bt(e);return r>=o.height-n.height-t}),Y())}var cr={drawer:V("[data-md-toggle=drawer]"),search:V("[data-md-toggle=search]")};function io(e){return cr[e].checked}function qe(e,t){cr[e].checked!==t&&cr[e].click()}function je(e){let t=cr[e];return b(t,"change").pipe(l(()=>t.checked),N(t.checked))}function $a(e,t){switch(e.constructor){case HTMLInputElement:return e.type==="radio"?/^Arrow/.test(t):!0;case HTMLSelectElement:case HTMLTextAreaElement:return!0;default:return e.isContentEditable}}function Ia(){return L(b(window,"compositionstart").pipe(l(()=>!0)),b(window,"compositionend").pipe(l(()=>!1))).pipe(N(!1))}function ao(){let e=b(window,"keydown").pipe(_(t=>!(t.metaKey||t.ctrlKey)),l(t=>({mode:io("search")?"search":"global",type:t.key,claim(){t.preventDefault(),t.stopPropagation()}})),_(({mode:t,type:r})=>{if(t==="global"){let n=_e();if(typeof n!="undefined")return!$a(n,r)}return!0}),fe());return Ia().pipe(x(t=>t?R:e))}function Me(){return new URL(location.href)}function ot(e){location.href=e.href}function so(){return new E}function co(e,t){if(typeof t=="string"||typeof t=="number")e.innerHTML+=t.toString();else if(t instanceof Node)e.appendChild(t);else if(Array.isArray(t))for(let r of t)co(e,r)}function M(e,t,...r){let n=document.createElement(e);if(t)for(let o of Object.keys(t))typeof t[o]!="undefined"&&(typeof t[o]!="boolean"?n.setAttribute(o,t[o]):n.setAttribute(o,""));for(let o of r)co(n,o);return n}function fr(e){if(e>999){let t=+((e-950)%1e3>99);return`${((e+1e-6)/1e3).toFixed(t)}k`}else return e.toString()}function fo(){return location.hash.substring(1)}function uo(e){let t=M("a",{href:e});t.addEventListener("click",r=>r.stopPropagation()),t.click()}function Fa(){return b(window,"hashchange").pipe(l(fo),N(fo()),_(e=>e.length>0),J(1))}function po(){return Fa().pipe(l(e=>se(`[id="${e}"]`)),_(e=>typeof e!="undefined"))}function Nr(e){let t=matchMedia(e);return Zt(r=>t.addListener(()=>r(t.matches))).pipe(N(t.matches))}function lo(){let e=matchMedia("print");return L(b(window,"beforeprint").pipe(l(()=>!0)),b(window,"afterprint").pipe(l(()=>!1))).pipe(N(e.matches))}function qr(e,t){return e.pipe(x(r=>r?t():R))}function ur(e,t={credentials:"same-origin"}){return ve(fetch(`${e}`,t)).pipe(ce(()=>R),x(r=>r.status!==200?Tt(()=>new Error(r.statusText)):H(r)))}function Ue(e,t){return ur(e,t).pipe(x(r=>r.json()),J(1))}function mo(e,t){let r=new DOMParser;return ur(e,t).pipe(x(n=>n.text()),l(n=>r.parseFromString(n,"text/xml")),J(1))}function pr(e){let t=M("script",{src:e});return I(()=>(document.head.appendChild(t),L(b(t,"load"),b(t,"error").pipe(x(()=>Tt(()=>new ReferenceError(`Invalid script: ${e}`))))).pipe(l(()=>{}),C(()=>document.head.removeChild(t)),Oe(1))))}function ho(){return{x:Math.max(0,scrollX),y:Math.max(0,scrollY)}}function bo(){return L(b(window,"scroll",{passive:!0}),b(window,"resize",{passive:!0})).pipe(l(ho),N(ho()))}function vo(){return{width:innerWidth,height:innerHeight}}function go(){return b(window,"resize",{passive:!0}).pipe(l(vo),N(vo()))}function yo(){return Q([bo(),go()]).pipe(l(([e,t])=>({offset:e,size:t})),J(1))}function lr(e,{viewport$:t,header$:r}){let n=t.pipe(X("size")),o=Q([n,r]).pipe(l(()=>Be(e)));return Q([r,t,o]).pipe(l(([{height:i},{offset:a,size:s},{x:f,y:c}])=>({offset:{x:a.x-f,y:a.y-c+i},size:s})))}(()=>{function e(n,o){parent.postMessage(n,o||"*")}function t(...n){return n.reduce((o,i)=>o.then(()=>new Promise(a=>{let s=document.createElement("script");s.src=i,s.onload=a,document.body.appendChild(s)})),Promise.resolve())}var r=class{constructor(n){this.url=n,this.onerror=null,this.onmessage=null,this.onmessageerror=null,this.m=a=>{a.source===this.w&&(a.stopImmediatePropagation(),this.dispatchEvent(new MessageEvent("message",{data:a.data})),this.onmessage&&this.onmessage(a))},this.e=(a,s,f,c,u)=>{if(s===this.url.toString()){let p=new ErrorEvent("error",{message:a,filename:s,lineno:f,colno:c,error:u});this.dispatchEvent(p),this.onerror&&this.onerror(p)}};let o=new EventTarget;this.addEventListener=o.addEventListener.bind(o),this.removeEventListener=o.removeEventListener.bind(o),this.dispatchEvent=o.dispatchEvent.bind(o);let i=document.createElement("iframe");i.width=i.height=i.frameBorder="0",document.body.appendChild(this.iframe=i),this.w.document.open(),this.w.document.write(` + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + + + +
+
+
+ + + + +
+
+
+ + + + + + + + + +
+
+ + + + + + + + +

Home

+ +
+

The Reloaded Memory Library

+ +

+ Psssh, nothing personnel kid +

+ + + Coverage + + + + NuGet + + + + Build Status + +
+ +

About

+

Reloaded.Memory is a high performance library which provides zero-cost abstractions for memory manipulation in C#.
+It is designed to be as fast as possible, with no overhead, while providing useful functionality to the user.

+
+

The library has the following characteristics.

+
+
    +
  • Zero Cost Abstractions: Performance equivalent to using raw pointers.
  • +
  • Stable API: Versions 9.0.0 and above have a fully stable, backwards compatible API.
  • +
  • Trimming Safe: The library is fully compatible with .NET Core's Linker.
  • +
  • Fully Documented: The library is fully tested & documented with XML comments.
  • +
  • Cross Platform: 99% of the library is fully compatible with Windows, Linux and MacOS across multiple CPU architectures.
  • +
  • Large Address Aware: The library can correctly leverage all 4GB in x86 processes.
  • +
+

This project guarantees binary backwards compatibility; meaning you can substitute the library with any newer version +without recompiling the source code. Should the need to introduce any breaking changes occur; much like the runtime.

+

Common Utilities

+
+

Common Classes within this Package Include

+
+

Memory Manipulation:

+ + + + + + + + + + + + + + + + + +
ActionDescription
MemoryAllows you to Read, Write, Allocate & Change Memory Protection for Current Process.
ExternalMemoryRead, Write, Allocate & Change Memory Protection but for Another Process.
+

Streams Management:

+ + + + + + + + + + + + + + + + + + + + + +
ActionDescription
BigEndian(Reader/Writer)Read/write raw data in memory as Big Endian.
LittleEndian(Reader/Writer)Read/write raw data in memory as Little Endian.
BufferedStreamReaderHigh performance alternative to BinaryReader.
+

Extensions:

+ + + + + + + + + + + + + + + + + + + + + +
ActionDescription
(Array/Span)ExtensionsUnsafe slicing, references without bounds checks and SIMD accelerated extensions.
StreamExtensionsExtensions for reading and writing from/to generics.
StringExtensionsCustom Hash Function(s) and unsafe character references.
+

Utilities:

+ + + + + + + + + + + + + + + + + + + + + + + + + +
ActionDescription
ArrayRental & ArrayRentalSliceSafe wrapper around ArrayPool<T> rentals.
BoxRepresents a boxed value type, providing build-time validation and automatic unboxing.
CircularBufferBasic high-performance circular buffer.
PinnableUtility for pinning C# objects for access from native code.
+

Base building blocks:

+ + + + + + + + + + + + + + + + + +
ActionDescription
Ptr<T> / MarshalledPtr<T>Abstraction over a pointer to arbitrary source.
FixedArrayPtr<T> & MarshalledFixedArrayPtr<T>Abstraction over a pointer with known length.
+

(This list is not exhaustive, please see the API Documentation for complete API)

+

Community Feedback

+

If you have questions/bug reports/etc. feel free to Open an Issue.

+

Contributions are welcome and encouraged. Feel free to implement new features, make bug fixes or suggestions so long as +they meet the quality standards set by the existing code in the repository.

+

For an idea as to how things are set up, see Reloaded Project Configurations.

+

Happy Hacking 💜

+ + + + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/search/search_index.json b/search/search_index.json new file mode 100644 index 0000000..eee3221 --- /dev/null +++ b/search/search_index.json @@ -0,0 +1 @@ +{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"Home","text":"The Reloaded Memory Library Psssh, nothing personnel kid"},{"location":"#about","title":"About","text":"

Reloaded.Memory is a high performance library which provides zero-cost abstractions for memory manipulation in C#. It is designed to be as fast as possible, with no overhead, while providing useful functionality to the user.

The library has the following characteristics.

  • Zero Cost Abstractions: Performance equivalent to using raw pointers.
  • Stable API: Versions 9.0.0 and above have a fully stable, backwards compatible API.
  • Trimming Safe: The library is fully compatible with .NET Core's Linker.
  • Fully Documented: The library is fully tested & documented with XML comments.
  • Cross Platform: 99% of the library is fully compatible with Windows, Linux and MacOS across multiple CPU architectures.
  • Large Address Aware: The library can correctly leverage all 4GB in x86 processes.

This project guarantees binary backwards compatibility; meaning you can substitute the library with any newer version without recompiling the source code. Should the need to introduce any breaking changes occur; much like the runtime.

"},{"location":"#common-utilities","title":"Common Utilities","text":"

Common Classes within this Package Include

Memory Manipulation:

Action Description Memory Allows you to Read, Write, Allocate & Change Memory Protection for Current Process. ExternalMemory Read, Write, Allocate & Change Memory Protection but for Another Process.

Streams Management:

Action Description BigEndian(Reader/Writer) Read/write raw data in memory as Big Endian. LittleEndian(Reader/Writer) Read/write raw data in memory as Little Endian. BufferedStreamReader High performance alternative to BinaryReader.

Extensions:

Action Description (Array/Span)Extensions Unsafe slicing, references without bounds checks and SIMD accelerated extensions. StreamExtensions Extensions for reading and writing from/to generics. StringExtensions Custom Hash Function(s) and unsafe character references.

Utilities:

Action Description ArrayRental & ArrayRentalSlice Safe wrapper around ArrayPool<T> rentals. Box Represents a boxed value type, providing build-time validation and automatic unboxing. CircularBuffer Basic high-performance circular buffer. Pinnable Utility for pinning C# objects for access from native code.

Base building blocks:

Action Description Ptr<T> / MarshalledPtr<T> Abstraction over a pointer to arbitrary source. FixedArrayPtr<T> & MarshalledFixedArrayPtr<T> Abstraction over a pointer with known length.

(This list is not exhaustive, please see the API Documentation for complete API)

"},{"location":"#community-feedback","title":"Community Feedback","text":"

If you have questions/bug reports/etc. feel free to Open an Issue.

Contributions are welcome and encouraged. Feel free to implement new features, make bug fixes or suggestions so long as they meet the quality standards set by the existing code in the repository.

For an idea as to how things are set up, see Reloaded Project Configurations.

Happy Hacking \ud83d\udc9c

"},{"location":"About-Memory/","title":"Memory API","text":"

Info

Reloaded.Memory provides various abstractions that can be used to wrap around contiguous regions of memory.

All APIs listed here are zero overhead.

Stuff listed here isn't that impressive, but it's the basic building block for what follows next.

"},{"location":"About-Memory/#memory-externalmemory","title":"Memory & ExternalMemory","text":"

Info

The Memory and ExternalMemory classes are the most basic abstractions provided by Reloaded.Memory. They allow you to access memory either within the current or a target process.

Raw PointerAnother Processw/ Memoryw/ ExternalMemory
while (ptr < maxAddress)\n{\nresult += *ptr;\nptr += 1;\n}\n
if (Polyfills.IsWindows())\nreturn Kernel32.ReadProcessMemory(_processHandle, location, (nuint)buffer, numBytes, out _);\n\nif (Polyfills.IsLinux())\nreturn Posix.process_vm_readv_k32(_processHandle, location, (nuint)buffer, numBytes);\n\n// And other cases!\n
// memory = Memory.Instance;\nwhile (ptr < maxAddress)\n{\nresult += memory.Read<nuint>((UIntPtr)ptr);\nptr += 1;\n}\n
// memory = new ExternalMemory(process);\nwhile (ptr < maxAddress)\n{\nresult += memory.Read<nuint>((UIntPtr)ptr);\nptr += 1;\n}\n

As you can see, with the library and its ICanReadWriteMemory interface; usage is unified across all sources. Instead of having to write different code for different sources (first 2 examples), you can now write the same code for all sources.

And of course, various different utility methods are provided to make your life easier.

Raw Pointer MarshallingAnother Processw/ Memoryw/ ExternalMemory
while (ptr < maxAddress)\nMarshal.StructureToPtr(items[x++], (nint)offset, false);\n
byte* bufferPtr = new byte[structSize];\nbool succeeded = ReadProcessMemory(offset, bufferPtr, (nuint)structSize);\nif (!succeeded)\nThrowHelpers.ThrowReadExternalMemoryExceptionWindows(offset, structSize);\n\nMarshal.PtrToStructure((nint)bufferPtr, value);\n
while (ptr < maxAddress)\nmemory.WriteWithMarshalling(ptr, items[x++]);\n
while (ptr < maxAddress)\nmemory.WriteWithMarshalling(ptr, items[x++]);\n

All silly boilerplate needed to manipulate different sources is gone; and this is all done with zero-overhead.

"},{"location":"About-Memory/#unified-memory-allocation-api","title":"Unified Memory Allocation API","text":"

Info

Structs like Memory and ExternalMemory employ ICanAllocateMemory API to make memory allocations convenient.

Regular Code (.NET 7+)Classic Code (<= .NET 7)w/ Memoryw/ ExternalMemory
var allocation = NativeMemory.Alloc(100);\n
var allocation = Marshal.AllocHGlobal(100);\n
var allocation = memory.Allocate(100);\n
var allocation = memory.Allocate(100);\n

Now you can allocate in another process in a consistent manner. Useful?

ICanAllocateMemory for ExternalMemory currently implemented in Windows only; PRs for Linux and OSX.

"},{"location":"About-Memory/#unified-permission-change-api","title":"Unified Permission Change API","text":"

Info

Structs like Memory and ExternalMemory employ ICanChangeMemoryProtection API to allow you to change memory permissions.

This allows you to make existing code etc. in memory writable for editing.

This Processw/ Memoryw/ ExternalMemory
if (Polyfills.IsWindows())\n{\nbool result = Kernel32.VirtualProtect(memoryAddress, (nuint)size, (Kernel32.MEM_PROTECTION)newProtection,\nout Kernel32.MEM_PROTECTION oldPermissions);\nif (!result)\nThrowHelpers.ThrowMemoryPermissionExceptionWindows(memoryAddress, size, newProtection);\n\nreturn (nuint)oldPermissions;\n}\n\nif (Polyfills.IsLinux() || Polyfills.IsMacOS())\n{\n// ... lot more boilerplate\n}\n
var oldPermissions = source.ChangeProtection(address, length, MemoryProtection.READ);\n
var oldPermissions = source.ChangeProtection(address, length, MemoryProtection.READ);\n

Pretty useful huh?

ICanChangeMemoryProtection for ExternalMemory currently implemented in Windows only; PRs for Linux and OSX are welcome.

"},{"location":"About-Memory/#extensions","title":"Extensions","text":"

Info

These interfaces, and combinations of them allow for some very useful utility methods to be made.

Temporary allocate a buffer:

// Automatically disposed, even on exception\nusing var alloc = memory.AllocateDisposable(DataSize);\n

Temporary change memory permission:

using var alloc = memory.ChangeProtectionDisposable(DataSize);\n

Temporary change memory permission, write data, and restore:

memory.SafeWrite(Alloc.Address, Data.AsSpanFast());\n
"},{"location":"About-Memory/#reference-benchmarks","title":"Reference Benchmarks","text":"

In most cases, the abstractions generate 1:1 code that matches exactly the same performance as working with raw pointers.

|                        Method |     Mean |   Error |  StdDev | Code Size | Allocated |\n|------------------------------ |---------:|--------:|--------:|----------:|----------:|\n|                ReadViaPointer | 130.7 ns | 0.77 ns | 0.69 ns |      49 B |         - |\n|                 ReadViaMemory | 132.4 ns | 0.71 ns | 0.66 ns |      52 B |         - |\n| ReadViaMemory_ViaOutParameter | 132.2 ns | 1.81 ns | 1.70 ns |      52 B |         - |\n|               WriteViaPointer | 117.4 ns | 1.55 ns | 1.45 ns |      48 B |         - |\n|                WriteViaMemory | 117.8 ns | 1.67 ns | 1.57 ns |      48 B |         - |\n

ReadViaPointer and WriteViaPointer are using raw pointers; remaining tests are using the abstractions.

"},{"location":"Extensions/ArrayExtensions/","title":"ArrayExtensions","text":"

Partially forked from Community Toolkit.

Utility class providing high performance extension methods for working with arrays.

ArrayExtensions is a utility class that provides extension methods for arrays, including methods for getting references without bounds checks, counting occurrences of a value, checking covariance, and converting arrays to spans.

"},{"location":"Extensions/ArrayExtensions/#methods","title":"Methods","text":""},{"location":"Extensions/ArrayExtensions/#dangerousgetreference","title":"DangerousGetReference","text":"
public static ref T DangerousGetReference<T>(this T[] array)\n

Returns a reference to the first element within a given T[] array, with no bounds checks. The caller is responsible for performing checks in case the returned value is dereferenced.

"},{"location":"Extensions/ArrayExtensions/#dangerousgetreferenceat","title":"DangerousGetReferenceAt","text":"
public static ref T DangerousGetReferenceAt<T>(this T[] array, int i)\n

Returns a reference to an element at a specified index within a given T[] array, with no bounds checks. The caller is responsible for ensuring the i parameter is valid.

"},{"location":"Extensions/ArrayExtensions/#count","title":"Count","text":"
public static int Count<T>(this T[] array, T value) where T : IEquatable<T>\n

Counts the number of occurrences of a given value in a target T[] array instance.

"},{"location":"Extensions/ArrayExtensions/#iscovariant","title":"IsCovariant","text":"
public static bool IsCovariant<T>(this T[] array)\n

Checks whether or not a given T[] array is covariant.

"},{"location":"Extensions/ArrayExtensions/#asspanfast","title":"AsSpanFast","text":"

Only supported on .NET 5 and above. Older runtimes will use default AsSpan.

public static Span<T> AsSpanFast<T>(this T[] data)\n

Converts a byte array to a Span without doing a null check.

"},{"location":"Extensions/ArrayExtensions/#usage","title":"Usage","text":""},{"location":"Extensions/ArrayExtensions/#get-reference-without-bounds-checks","title":"Get Reference without Bounds Checks","text":"
int[] array = new int[] { 1, 2, 3 };\nref int firstElement = ref array.DangerousGetReference();\n
"},{"location":"Extensions/ArrayExtensions/#get-reference-at-specific-index-without-bounds-checks","title":"Get Reference at Specific Index without Bounds Checks","text":"
int[] array = new int[] { 1, 2, 3 };\nref int elementAtTwo = ref array.DangerousGetReferenceAt(2);\n
"},{"location":"Extensions/ArrayExtensions/#count-occurrences-of-a-value","title":"Count Occurrences of a Value","text":"
int[] array = new int[] { 1, 2, 2, 3, 2 };\nint count = array.Count(2);\n
"},{"location":"Extensions/ArrayExtensions/#check-covariance","title":"Check Covariance","text":"
object[] array = new object[] { \"a\", \"b\", \"c\" };\nbool isCovariant = array.IsCovariant<string>();\n
"},{"location":"Extensions/ArrayExtensions/#convert-array-to-span-without-null-check","title":"Convert Array to Span without Null Check","text":"
int[] array = new int[] { 1, 2, 3 };\nSpan<int> span = array.AsSpanFast();\n
"},{"location":"Extensions/BoolExtensions/","title":"BoolExtensions","text":"

Forked from Community Toolkit.

Utility class providing high performance extension methods for working with the bool type.

BoolExtensions is a utility class that provides extension methods for the bool type, including converting bool values to byte, int, and long masks.

"},{"location":"Extensions/BoolExtensions/#methods","title":"Methods","text":""},{"location":"Extensions/BoolExtensions/#tobyte","title":"ToByte","text":"
public static unsafe byte ToByte(this bool flag)\n

Converts the given bool value into a byte. Returns 1 if flag is true, 0 otherwise. This method does not contain branching instructions.

"},{"location":"Extensions/BoolExtensions/#tobitwisemask32","title":"ToBitwiseMask32","text":"
public static unsafe int ToBitwiseMask32(this bool flag)\n

Converts the given bool value to an int mask with all bits representing the value of the input flag (either 0xFFFFFFFF or 0x00000000). This method does not contain branching instructions.

"},{"location":"Extensions/BoolExtensions/#tobitwisemask64","title":"ToBitwiseMask64","text":"
public static unsafe long ToBitwiseMask64(this bool flag)\n

Converts the given bool value to a long mask with all bits representing the value of the input flag (either all 1s or 0s). This method does not contain branching instructions.

"},{"location":"Extensions/BoolExtensions/#usage","title":"Usage","text":""},{"location":"Extensions/BoolExtensions/#convert-bool-to-byte","title":"Convert Bool to Byte","text":"
bool flag = true;\nbyte result = flag.ToByte();\n
"},{"location":"Extensions/BoolExtensions/#convert-bool-to-int-mask","title":"Convert Bool to Int Mask","text":"
bool flag = true;\nint mask = flag.ToBitwiseMask32();\n
"},{"location":"Extensions/BoolExtensions/#convert-bool-to-long-mask","title":"Convert Bool to Long Mask","text":"
bool flag = true;\nlong mask = flag.ToBitwiseMask64();\n
"},{"location":"Extensions/EndianExtensions/","title":"EndianExtensions","text":"

Provides extension methods for converting between endianness.

EndianExtensions is a static class that offers methods to convert primitive data types and any structure implementing the ICanReverseEndian interface to big or little endian format.

The conversions check the system's endianness and only perform byte-swapping if necessary, making the operation efficient by avoiding redundant processing on systems with matching endianness.

The JIT will eliminate no-operations here, so e.g. calling AsLittleEndian on a Little Endian machine has 0 overhead.

"},{"location":"Extensions/EndianExtensions/#methods","title":"Methods","text":""},{"location":"Extensions/EndianExtensions/#aslittleendian-overloads-for-various-types","title":"AsLittleEndian (Overloads for various types)","text":"
public static byte AsLittleEndian(this byte value)\npublic static sbyte AsLittleEndian(this sbyte value)\npublic static short AsLittleEndian(this short value)\npublic static ushort AsLittleEndian(this ushort value)\npublic static int AsLittleEndian(this int value)\npublic static uint AsLittleEndian(this uint value)\npublic static long AsLittleEndian(this long value)\npublic static ulong AsLittleEndian(this ulong value)\npublic static float AsLittleEndian(this float value)\npublic static double AsLittleEndian(this double value)\npublic static T AsLittleEndian<T>(this T value) where T : struct, ICanReverseEndian\n

Converts the given value to little endian format. If the system is already little endian, no conversion is performed.

"},{"location":"Extensions/EndianExtensions/#parameters","title":"Parameters","text":"
  • value: The value to convert to little endian.
"},{"location":"Extensions/EndianExtensions/#returns","title":"Returns","text":"

The value in little endian format.

"},{"location":"Extensions/EndianExtensions/#asbigendian-overloads-for-various-types","title":"AsBigEndian (Overloads for various types)","text":"
public static byte AsBigEndian(this byte value)\npublic static sbyte AsBigEndian(this sbyte value)\npublic static short AsBigEndian(this short value)\npublic static ushort AsBigEndian(this ushort value)\npublic static int AsBigEndian(this int value)\npublic static uint AsBigEndian(this uint value)\npublic static long AsBigEndian(this long value)\npublic static ulong AsBigEndian(this ulong value)\npublic static float AsBigEndian(this float value)\npublic static double AsBigEndian(this double value)\npublic static T AsBigEndian<T>(this T value) where T : struct, ICanReverseEndian\n

Converts the given value to big endian format. If the system is already big endian, no conversion is performed.

"},{"location":"Extensions/EndianExtensions/#parameters_1","title":"Parameters","text":"
  • value: The value to convert to big endian.
"},{"location":"Extensions/EndianExtensions/#returns_1","title":"Returns","text":"

The value in big endian format.

"},{"location":"Extensions/EndianExtensions/#usage","title":"Usage","text":""},{"location":"Extensions/EndianExtensions/#convert-an-integer-to-little-endian-format","title":"Convert an Integer to Little Endian Format","text":"
int myValue = 12345678;\nint littleEndianValue = myValue.AsLittleEndian();\n
"},{"location":"Extensions/EndianExtensions/#convert-a-double-to-big-endian-format","title":"Convert a Double to Big Endian Format","text":"
double myValue = 123.456;\ndouble bigEndianValue = myValue.AsBigEndian();\n
"},{"location":"Extensions/EndianExtensions/#convert-a-custom-structure-to-big-endian-format","title":"Convert a Custom Structure to Big Endian Format","text":"

For structs which implement ICanReverseEndian

var myStruct = new MyStruct { /* ... */ };\nvar asBig = myStruct.AsBigEndian();\n
"},{"location":"Extensions/EnumExtensions/","title":"EnumExtensions","text":"

Provides high-performance extension methods for working with enums.

EnumExtensions is a utility class that , including checking for the presence of a specified flag in an enum value using unsafe code for faster execution.

"},{"location":"Extensions/EnumExtensions/#methods","title":"Methods","text":""},{"location":"Extensions/EnumExtensions/#hasflagfast","title":"HasFlagFast","text":"
public static bool HasFlagFast<T>(this T value, T flag) where T : unmanaged, Enum\n

Determines if the given enum has a specified flag. This method uses unsafe code for faster execution and skips type check.

"},{"location":"Extensions/EnumExtensions/#parameters","title":"Parameters","text":"
  • value: The value to check.
  • flag: The flag to check.
"},{"location":"Extensions/EnumExtensions/#returns","title":"Returns","text":"

true if the enum is contained in the value, false otherwise.

"},{"location":"Extensions/EnumExtensions/#type-parameters","title":"Type Parameters","text":"
  • T: The type to check the flag of.
"},{"location":"Extensions/EnumExtensions/#exceptions","title":"Exceptions","text":"
  • NotSupportedException: This type of enum is not supported.
"},{"location":"Extensions/EnumExtensions/#usage","title":"Usage","text":""},{"location":"Extensions/EnumExtensions/#check-if-an-enum-value-contains-a-specific-flag","title":"Check if an Enum Value Contains a Specific Flag","text":"
[Flags]\nenum MyEnum : int\n{\nNone = 0,\nFlag1 = 1,\nFlag2 = 2,\nFlag3 = 4,\n}\n\nMyEnum value = MyEnum.Flag1 | MyEnum.Flag3;\nbool hasFlag1 = value.HasFlagFast(MyEnum.Flag1); // True\nbool hasFlag2 = value.HasFlagFast(MyEnum.Flag2); // False\nbool hasFlag3 = value.HasFlagFast(MyEnum.Flag3); // True\n
"},{"location":"Extensions/SpanExtensions/","title":"SpanExtensions","text":"

Partially forked from Community Toolkit.

Utility class providing high performance extension methods for working with spans.

SpanExtensions is a utility class that provides extension methods for spans, including methods for casting, slicing, replacing elements, and finding offsets.

"},{"location":"Extensions/SpanExtensions/#methods","title":"Methods","text":""},{"location":"Extensions/SpanExtensions/#castfast","title":"CastFast","text":"

Not accelerated on .NET Framework and Standard 2.0

public static Span<TTo> CastFast<TFrom, TTo>(this Span<TFrom> data) where TFrom : struct where TTo : struct\n
Casts a Span<TFrom> to a Span<TTo> without copying the underlying data.

"},{"location":"Extensions/SpanExtensions/#dangerousgetreference","title":"DangerousGetReference","text":"

public static ref T DangerousGetReference<T>(this Span<T> span)\n
Returns a reference to the first element within a given Span<T>, with no bounds checks.

"},{"location":"Extensions/SpanExtensions/#dangerousgetreferenceat","title":"DangerousGetReferenceAt","text":"

public static ref T DangerousGetReferenceAt<T>(this Span<T> span, int i)\n
Returns a reference to an element at a specified index within a given Span<T>, with no bounds checks. The caller is responsible for ensuring the i parameter is valid.

"},{"location":"Extensions/SpanExtensions/#asbytes","title":"AsBytes","text":"

public static Span<byte> AsBytes<T>(this Span<T> span) where T : unmanaged\n
Converts a Span<T> to a Span<byte> without copying the underlying data.

"},{"location":"Extensions/SpanExtensions/#cast","title":"Cast","text":"

public static Span<TTo> Cast<TFrom, TTo>(this Span<TFrom> span) where TFrom : unmanaged where TTo : unmanaged\n
Casts a Span<TFrom> to a Span<TTo> without copying the underlying data, when both types are unmanaged.

"},{"location":"Extensions/SpanExtensions/#indexof","title":"IndexOf","text":"
public static unsafe int IndexOf<T>(this Span<T> span, ref T value)\n

Gets the index of an element within given Span<T> based on a reference to an element inside the Span<T>.

"},{"location":"Extensions/SpanExtensions/#count","title":"Count","text":"

public static int Count<T>(this Span<T> span, T value) where T : IEquatable<T>\n
Counts the number of occurrences of a given value in a target Span<T> instance.

"},{"location":"Extensions/SpanExtensions/#slicefast","title":"SliceFast","text":"

Not accelerated on .NET Framework and Standard 2.0

public static Span<T> SliceFast<T>(this Span<T> data, int start, int length)\npublic static ReadOnlySpan<T> SliceFast<T>(this ReadOnlySpan<T> data, int start, int length)\npublic static ReadOnlySpan<T> SliceFast<T>(this ReadOnlySpan<T> data, Range range)\npublic static Span<T> SliceFast<T>(this Span<T> data, Range range)\npublic static Span<T> SliceFast<T>(this Span<T> data, int start)\npublic static ReadOnlySpan<T> SliceFast<T>(this ReadOnlySpan<T> data, int start)\n
Performs a slice operation on a Span<T> or ReadOnlySpan<T> without performing bounds checks. This supports ranges, so span.SliceFast(1..3) is valid.

"},{"location":"Extensions/SpanExtensions/#replace","title":"Replace","text":"

public static Span<char> Replace(this Span<char> data, char oldValue, char newValue, Span<char> buffer)\npublic static unsafe Span<T> Replace<T>(this Span<T> data, T oldValue, T newValue, Span<T> buffer) where T : unmanaged, IEquatable<T>\n
Replaces all occurrences of a specified value with another value in a given Span<T>.

"},{"location":"Extensions/SpanExtensions/#findalloffsetsofbyte","title":"FindAllOffsetsOfByte","text":"

Missing SIMD path for non-x86/x64 platforms. PRs are welcome.

public static List<int> FindAllOffsetsOfByte(this ReadOnlySpan<byte> data, byte value)\npublic static List<int> FindAllOffsetsOfByte(this ReadOnlySpan<byte> data, byte value, int offsetCountHint)\n
Finds all the offsets of a given byte value in a target ReadOnlySpan<byte> instance. The second overload allows specifying an optional offsetCountHint parameter to preallocate the list capacity.

"},{"location":"Extensions/SpanExtensions/#usage","title":"Usage","text":""},{"location":"Extensions/SpanExtensions/#get-reference-without-bounds-checks","title":"Get Reference without Bounds Checks","text":"
Span<int> span = new int[] { 1, 2, 3 };\nref int firstElement = ref span.DangerousGetReference();\n
"},{"location":"Extensions/SpanExtensions/#get-reference-at-specific-index-without-bounds-checks","title":"Get Reference at Specific Index without Bounds Checks","text":"
Span<int> span = new int[] { 1, 2, 3 };\nref int elementAtTwo = ref span.DangerousGetReferenceAt(2);\n
"},{"location":"Extensions/SpanExtensions/#convert-span-to-byte-span","title":"Convert Span to Byte Span","text":"
Span<int> intSpan = new int[] { 1, 2, 3 };\nSpan<byte> byteSpan = intSpan.AsBytes();\n
"},{"location":"Extensions/SpanExtensions/#cast-span","title":"Cast Span","text":"
Span<byte> byteSpan = new byte[] { 1, 2, 3, 4 };\nSpan<int> intSpan = byteSpan.Cast<byte, int>();\n
"},{"location":"Extensions/SpanExtensions/#find-index-of-an-element","title":"Find Index of an Element","text":"
Span<int> span = new int[] { 1, 2, 3, 4, 5 };\nref int value = ref span[3];\nint index = span.IndexOf(ref value); // index = 3\n
"},{"location":"Extensions/SpanExtensions/#count-occurrences-of-a-value","title":"Count Occurrences of a Value","text":"
Span<int> span = new int[] { 1, 2, 2, 3, 2 };\nint count = span.Count(2); // 3\n
"},{"location":"Extensions/SpanExtensions/#slice-span-without-bounds-checks","title":"Slice Span Without Bounds Checks","text":"
Span<int> span = new int[] { 1, 2, 3, 4, 5 };\nSpan<int> slicedSpan = span.SliceFast(1, 3);\n
"},{"location":"Extensions/SpanExtensions/#replace-elements-in-a-span","title":"Replace Elements in a Span","text":"
Span<char> span = \"hello world\".ToCharArray();\nSpan<char> buffer = new char[span.Length];\nSpan<char> replacedSpan = span.Replace('l', 'x', buffer);\n
"},{"location":"Extensions/SpanExtensions/#find-all-offsets-of-a-byte","title":"Find All Offsets of a Byte","text":"
byte[] data = new byte[] { 1, 2, 3, 2, 4, 2 };\nReadOnlySpan<byte> span = data;\nList<int> offsets = span.FindAllOffsetsOfByte(2);\n
"},{"location":"Extensions/SpanExtensions/#find-all-offsets-of-a-byte-with-offset-count-hint","title":"Find All Offsets of a Byte with Offset Count Hint","text":"
byte[] data = new byte[] { 1, 2, 3, 2, 4, 2 };\nReadOnlySpan<byte> span = data;\nList<int> offsets = span.FindAllOffsetsOfByte(2, 3);\n
"},{"location":"Extensions/StreamExtensions/","title":"StreamExtensions","text":"

Utility class providing high performance extension methods for working with Stream objects.

StreamExtensions is a utility class that provides extension methods for the Stream type, including padding, writing, and reading unmanaged and marshalled structures.

"},{"location":"Extensions/StreamExtensions/#methods","title":"Methods","text":""},{"location":"Extensions/StreamExtensions/#addpadding","title":"AddPadding","text":"

public static void AddPadding<TStream>(this TStream stream, int alignment)\n
Pads the stream with any/random bytes until it is aligned to the specified alignment. The padding bytes depend on the implementation of Stream.SetLength.

"},{"location":"Extensions/StreamExtensions/#addpadding_1","title":"AddPadding","text":"

public static void AddPadding<TStream>(this TStream stream, byte value, int alignment = 2048)\n
Pads the stream with the specified value bytes until it is aligned to the specified alignment.

"},{"location":"Extensions/StreamExtensions/#write","title":"Write","text":"

public static void Write<TStream, T>(this TStream stream, Span<T> structure) where T : unmanaged\n
Appends an unmanaged structure onto the given stream and advances the position.

"},{"location":"Extensions/StreamExtensions/#write_1","title":"Write","text":"

public static void Write<TStream, T>(this TStream stream, in T structure) where T : unmanaged\n
Appends an unmanaged structure onto the given stream and advances the position.

"},{"location":"Extensions/StreamExtensions/#writemarshalled","title":"WriteMarshalled","text":"

public static void WriteMarshalled<TStream, T>(this TStream stream, T item)\n
Appends a managed/marshalled structure onto the given stream and advances the position.

"},{"location":"Extensions/StreamExtensions/#writemarshalled_1","title":"WriteMarshalled","text":"

public static void WriteMarshalled<TStream, T>(this TStream stream, T[] item)\n
Appends an array of managed/marshalled structures onto the given stream and advances the position.

"},{"location":"Extensions/StreamExtensions/#writemarshalled_2","title":"WriteMarshalled","text":"

public static void WriteMarshalled<TStream, T>(this TStream stream, Span<T> item)\n
Appends a span of managed/marshalled structures onto the given stream and advances the position.

"},{"location":"Extensions/StreamExtensions/#read","title":"Read","text":"

public static void Read<TStream, T>(this TStream stream, out T result) where T : unmanaged\n
Reads a single unmanaged structure of type T from the stream.

"},{"location":"Extensions/StreamExtensions/#read_1","title":"Read","text":"

public static void Read<TStream, T>(this TStream stream, T[] output) where T : unmanaged\n
Reads a span of unmanaged structures of type T from the stream into the provided output array.

"},{"location":"Extensions/StreamExtensions/#read_2","title":"Read","text":"

public static void Read<TStream, T>(this TStream stream, Span<T> output) where T : unmanaged\n
Reads a span of unmanaged structures of type T from the stream into the provided output span.

"},{"location":"Extensions/StreamExtensions/#readmarshalled","title":"ReadMarshalled","text":"

public static void ReadMarshalled<TStream, T>(this TStream stream, out T result)\n
Reads a single marshalled structure of type T from the stream.

"},{"location":"Extensions/StreamExtensions/#readmarshalled_1","title":"ReadMarshalled","text":"

public static void ReadMarshalled<TStream, T>(this TStream stream, T[] output)\n
Reads a span of marshalled structures of type T from the stream into the provided output array.

"},{"location":"Extensions/StreamExtensions/#readmarshalled_2","title":"ReadMarshalled","text":"

public static void ReadMarshalled<TStream, T>(this TStream stream, Span<T> output)\n
Reads a span of marshalled structures of type T from the stream into the provided output span.

"},{"location":"Extensions/StreamExtensions/#usage","title":"Usage","text":""},{"location":"Extensions/StreamExtensions/#pad-stream-with-random-bytes","title":"Pad Stream with Random Bytes","text":"
using var stream = new MemoryStream();\nstream.AddPadding(4096);\n
"},{"location":"Extensions/StreamExtensions/#pad-stream-with-specific-byte-value","title":"Pad Stream with Specific Byte Value","text":"
using var stream = new MemoryStream();\nstream.AddPadding(0xFF, 4096);\n
"},{"location":"Extensions/StreamExtensions/#write-unmanaged-structure","title":"Write Unmanaged Structure","text":"
using var stream = new MemoryStream();\nVector2 structure = new Vector2(1, 2);\nstream.Write(structure);\n
"},{"location":"Extensions/StreamExtensions/#write-marshalled-structure","title":"Write Marshalled Structure","text":"
using var stream = new MemoryStream();\nMyStruct item = new MyStruct { Value1 = 1, Value2 = \"Hello\" };\nstream.WriteMarshalled(item);\n
"},{"location":"Extensions/StreamExtensions/#read-unmanaged-structure","title":"Read Unmanaged Structure","text":"
using var stream = new MemoryStream();\nstream.Read(out Vector2 result);\n
"},{"location":"Extensions/StreamExtensions/#read-marshalled-structure","title":"Read Marshalled Structure","text":"
using var stream = new MemoryStream();\nstream.ReadMarshalled(out MyStruct result);\n
"},{"location":"Extensions/StreamExtensions/#read-span-of-unmanaged-structures","title":"Read Span of Unmanaged Structures","text":"
using var stream = new MemoryStream();\nVector2[] output = new Vector2[10];\nstream.Read(output);\n
"},{"location":"Extensions/StreamExtensions/#read-span-of-marshalled-structures","title":"Read Span of Marshalled Structures","text":"
using var stream = new MemoryStream();\nMyStruct[] output = new MyStruct[10];\nstream.ReadMarshalled(output);\n
"},{"location":"Extensions/StringExtensions/","title":"StringExtensions","text":"

Partially forked from Community Toolkit.

Utility class providing high performance extension methods for working with the string type.

StringExtensions is a utility class that provides extension methods for the string type, including getting references to string elements, and counting the number of occurrences of a character in a string.

"},{"location":"Extensions/StringExtensions/#methods","title":"Methods","text":""},{"location":"Extensions/StringExtensions/#dangerousgetreference","title":"DangerousGetReference","text":"
public static ref char DangerousGetReference(this string text)\n

Returns a reference to the first element within a given string, with no bounds checks. It is the caller's responsibility to perform bounds checks when dereferencing the returned value.

"},{"location":"Extensions/StringExtensions/#dangerousgetreferenceat","title":"DangerousGetReferenceAt","text":"
public static ref char DangerousGetReferenceAt(this string text, int i)\n

Returns a reference to an element at a specified index within a given string, with no bounds checks. It is the caller's responsibility to ensure the i parameter is valid.

"},{"location":"Extensions/StringExtensions/#count","title":"Count","text":"
public static int Count(this string text, char c)\n

Counts the number of occurrences of a given character in a target string instance.

"},{"location":"Extensions/StringExtensions/#gethashcodefast","title":"GetHashCodeFast","text":"

SIMD method currently restricted to .NET 7+. PRs for backports are welcome.

Will produce different hashes depending on runtime or CPU.

Optimised for File Paths specifically

public static nuint GetHashCodeFast(string text)\npublic static unsafe nuint GetHashCodeFast(this ReadOnlySpan<char> text)\n

Faster hashcode for strings; but does not randomize between application runs.

Use this method if and only if 'Denial of Service' attacks are not a concern (i.e. never used for free-form user input), or are otherwise mitigated.

This method does not provide guarantees about producing the same hash across different machines or library versions, or runtime; only for the current process. Instead, it prioritises speed over all.

"},{"location":"Extensions/StringExtensions/#gethashcodelowerfast","title":"GetHashCodeLowerFast","text":"

SIMD method currently restricted to .NET 7+. PRs for backports are welcome.

Will produce different hashes depending on runtime or CPU.

Optimised for File Paths specifically

public static nuint GetHashCodeLowerFast(this string text)\npublic static unsafe nuint GetHashCodeLowerFast(this ReadOnlySpan<char> text)\n

Faster hashcode for strings, hashed in lower (invariant) case; does not randomize between application runs.

Use this method if and only if 'Denial of Service' attacks are not a concern (i.e. never used for free-form user input), or are otherwise mitigated.

This method does not provide guarantees about producing the same hash across different machines or library versions, or runtime; only for the current process. Instead, it prioritises speed over all.

"},{"location":"Extensions/StringExtensions/#tolowerinvariantfast","title":"ToLowerInvariantFast","text":"
public static string ToLowerInvariantFast(this string text)\npublic static unsafe void ToLowerInvariantFast(this ReadOnlySpan<char> text, Span<char> target)\n

Converts the given string to lower case (invariant casing) using the fastest possible implementation. This method is optimized for performance but currently has limitations for short non-ASCII inputs.

"},{"location":"Extensions/StringExtensions/#toupperinvariantfast","title":"ToUpperInvariantFast","text":"
public static string ToUpperInvariantFast(this string text)\npublic static unsafe void ToUpperInvariantFast(this ReadOnlySpan<char> text, Span<char> target)\n

Converts the given string to upper case (invariant casing) using the fastest possible implementation. This method is optimized for performance but currently has limitations for short non-ASCII inputs.

"},{"location":"Extensions/StringExtensions/#usage","title":"Usage","text":""},{"location":"Extensions/StringExtensions/#get-reference-to-first-element-in-string","title":"Get Reference to First Element in String","text":"
string text = \"Hello, world!\";\nref char firstCharRef = ref text.DangerousGetReference();\n
"},{"location":"Extensions/StringExtensions/#get-reference-to-element-at-index-in-string","title":"Get Reference to Element at Index in String","text":"
string text = \"Hello, world!\";\nint index = 4;\nref char charAtIndexRef = ref text.DangerousGetReferenceAt(index);\n
"},{"location":"Extensions/StringExtensions/#count-character-occurrences-in-string","title":"Count Character Occurrences in String","text":"
string text = \"Hello, world!\";\nchar targetChar = 'l';\nint count = text.Count(targetChar);\n
"},{"location":"Extensions/StringExtensions/#get-fast-hash-code","title":"Get Fast Hash Code","text":"
string text = \"Hello, world!\";\nnuint fastHashCode = text.GetHashCodeFast();\n
"},{"location":"Extensions/StringExtensions/#get-lower-case-hash-code","title":"Get Lower Case Hash Code","text":"
string text = \"Hello, World!\";\nnuint lowerCaseHashCode = text.GetHashCodeLowerFast();\n
"},{"location":"Extensions/StringExtensions/#convert-string-to-lower-case-invariant-fast","title":"Convert String to Lower Case Invariant Fast","text":"
string text = \"Hello, WORLD!\";\nstring lowerInvariant = text.ToLowerInvariantFast(); // hello, world!\n
"},{"location":"Extensions/StringExtensions/#convert-string-to-upper-case-invariant-fast","title":"Convert String to Upper Case Invariant Fast","text":"
string text = \"hello, world!\";\nstring upperInvariant = text.ToUpperInvariantFast(); // HELLO, WORLD!\n
"},{"location":"Extensions/StringExtensions/#convert-readonlyspan-to-lower-case-invariant-fast","title":"Convert ReadOnlySpan to Lower Case Invariant Fast","text":"
string text = \"Hello, WORLD!\";\nSpan<char> target = stackalloc char[textSpan.Length]; // Careful with string length!\ntext.AsSpan().ToLowerInvariantFast(target); // hello, world! (on stack)\n
"},{"location":"Extensions/StringExtensions/#convert-readonlyspan-to-upper-case-invariant-fast","title":"Convert ReadOnlySpan to Upper Case Invariant Fast","text":"
string text = \"hello, world!\";\nSpan<char> target = stackalloc char[textSpan.Length]; // Careful with string length!\ntext.AsSpan().ToLowerInvariantFast(target); // HELLO, WORLD! (on stack)\n
"},{"location":"Extensions/VectorExtensions/","title":"VectorExtensions","text":"

Utility class providing high performance extension methods for working with the Vector struct.

VectorExtensions is a utility class that provides extension methods for the Vector struct.

"},{"location":"Extensions/VectorExtensions/#methods","title":"Methods","text":""},{"location":"Extensions/VectorExtensions/#loadunsafe","title":"LoadUnsafe","text":"
internal static Vector<T> LoadUnsafe<T>(ref T source, nuint elementOffset) where T : struct\n

Loads an element at a specified offset into a vector. Unsafe operations are used for performance reasons.

"},{"location":"Extensions/VectorExtensions/#storeunsafe","title":"StoreUnsafe","text":"
internal static void StoreUnsafe<T>(this Vector<T> source, ref T destination, nuint elementOffset) where T : struct\n

Stores an element from a vector into the destination + offset. Unsafe operations are used for performance reasons.

"},{"location":"Extensions/VectorExtensions/#usage","title":"Usage","text":""},{"location":"Extensions/VectorExtensions/#load-element-into-a-vector-at-an-offset","title":"Load Element into a Vector at an Offset","text":"
int[] array = new int[] { 1, 2, 3, 4, 5 };\nref int source = ref array[0];\nnuint elementOffset = 2;\nVector<int> vector = VectorExtensions.LoadUnsafe(ref source, elementOffset);\n
"},{"location":"Extensions/VectorExtensions/#store-element-from-a-vector-to-destination-offset","title":"Store Element from a Vector to Destination + Offset","text":"
Vector<int> vector = new Vector<int>(new int[] { 1, 2, 3, 4 });\nint[] destinationArray = new int[vector.Count];\nref int destination = ref destinationArray[0];\nnuint elementOffset = 1;\nvector.StoreUnsafe(ref destination, elementOffset);\n
"},{"location":"Pointers/FixedArrayPtr/","title":"FixedArrayPtr<T> and MarshalledFixedArrayPtr<T>","text":"

Abstraction for a pointer to a value of type T with a known length.

Zero overhead but not 1:1 codegen in all scenarios. e.g. Multiplying an element in place via Setter can be slower (.NET 7).

A helper to allow you to manage a collection of items in unmanaged, static memory; for example, find an item.

"},{"location":"Pointers/FixedArrayPtr/#properties","title":"Properties","text":"
  • Pointer: A Ptr representing the memory address of the first element in the fixed-size array.
  • Count: The number of elements in the fixed-size array.
  • ArraySize: The total size in bytes of the fixed-size array.
  • "},{"location":"Pointers/FixedArrayPtr/#examples","title":"Examples","text":""},{"location":"Pointers/FixedArrayPtr/#initialization","title":"Initialization","text":"
    var ptr = new FixedArrayPtr<int>(address, count);\n
    • Address: The memory address of the first element in the fixed-size array.
    • Count: The number of elements in the fixed-size array.
    "},{"location":"Pointers/FixedArrayPtr/#element-access","title":"Element Access","text":"

    The following methods should be used with in memory/RAM addresses. See Memory Read/Write for APIs that work with ICanReadWriteMemory implementations.

    ref T AsRef(int index);\nT Get(int index);\nvoid Get(int index, out T value);\nvoid Set(int index, in T value);\n

    These methods provide access to individual elements in the fixed-size array. The AsRef() method returns a reference to an element, allowing for direct modification of the element's value. The Get() and Set() methods retrieve and update the values of elements at specified indices.

    "},{"location":"Pointers/FixedArrayPtr/#memory-readwrite","title":"Memory Read/Write","text":"

    T Get<TSource>(TSource source, int index);\nvoid Get<TSource>(TSource source, int index, out T value);\nvoid Set<TSource>(TSource source, int index, in T value);\n
    These methods provide access to individual elements in the fixed-size array, allowing read and write operations to be performed on an implementation of ICanReadWriteMemory. This can be useful when working with external processes or other memory sources.

    "},{"location":"Pointers/FixedArrayPtr/#copying","title":"Copying","text":"
    void CopyFrom(Span<T> sourceArray, int length);\nvoid CopyFrom(Span<T> sourceArray, int length, int sourceIndex, int destinationIndex);\nvoid CopyTo(Span<T> destinationArray, int length);\nvoid CopyTo(Span<T> destinationArray, int length, int sourceIndex, int destinationIndex);\n

    These methods provide copying functionality between the fixed-size array and managed arrays. CopyFrom() copies elements from a managed array to the fixed-size array, and CopyTo() copies elements from the fixed-size array to a managed array.

    Both methods support copying a specified number of elements, as well as specifying source and destination indices for the copy operation.

    "},{"location":"Pointers/FixedArrayPtr/#search","title":"Search","text":"
    bool Contains(in T item);\nbool Contains<TSource>(TSource source, in T item);\nint IndexOf(in T item);\nint IndexOf<TSource>(TSource source, in T item);\n

    These methods provide search functionality for the fixed-size array, allowing you to check for the existence of an element or find its index. The Contains() methods return true if the specified item is found in the array, and the IndexOf() methods return the index of the first occurrence of the specified item or -1 if the item is not found.

    "},{"location":"Pointers/FixedArrayPtr/#sourcedfixedarrayptrt","title":"SourcedFixedArrayPtr<T>","text":"

    This is a tuple of FixedArrayPtr<T> and TSource.

    API surface is the same, all methods are delegated to underlying FixedArrayPtr<T>.

    Notably however, this API enables the use of LINQ; i.e. the following are now valid:

    foreach (int value in sourcedFixedArrayPtr)\n{\n// ...\n}\n
    sourcedFixedArrayPtr.Max(x => x);\n

    etc.

    "},{"location":"Pointers/Ptr/","title":"Ptr<T> and MarshalledPtr<T>","text":"

    Abstraction for a pointer to a value of type T.

    This type was formerly called BlittablePointer<T> and ArrayPtr<T> in old library versions.

    Zero overhead but not 1:1 codegen in all scenarios. e.g. Multiplying an element in place via Setter can be slower (.NET 7).

    A helper to allow you to do two things:

    • Use pointer arithmetic on anything implementing ICanReadWriteMemory. (e.g. Memory of External Process).
    • To use in generics.

    The type MarshalledPtr<T> also exists, this is a special type of Ptr<T> that marshals the elements as they are read/written; with pointer arithmetic being performed on the marshalled size of the object rather than the raw size.

    "},{"location":"Pointers/Ptr/#examples","title":"Examples","text":"

    Basically, the Ptr<T> type is just a regular pointer, with all of the operations you would expect from a pointer; except that it can be used in Generics, and also read/write to more than just RAM.

    "},{"location":"Pointers/Ptr/#initialization","title":"Initialization","text":"

    The Ptr<T> type supports implicit conversions to/from raw pointers.

    int someValue = 42;\nPtr<int> ptr = &someValue;\nint* ptr2 = intPtr;\n
    "},{"location":"Pointers/Ptr/#asref","title":"AsRef","text":"

    Pointers can be converted for references.

    ref int valueFromPtr = ref intPtr.AsRef();\nConsole.WriteLine($\"Value from pointer: {valueFromPtr}\");\n

    This can be especially useful for game modding APIs, the end user can for example do this:

    ref var playerCount = ref State.NumberOfPlayers.AsRef();\nplayerCount = 5;\n

    Completely avoiding pointer arithmetic; which is friendly to non-programmers.

    "},{"location":"Pointers/Ptr/#pointer-arithmetic","title":"Pointer Arithmetic","text":"

    You can do regular arithmetic on pointers, e.g. add 1 to go to next value.

    Ptr<int> arrayIntPtr = arrayPtr;\nPtr<int> offsetArrayIntPtr = arrayIntPtr + 2;\n\nConsole.WriteLine($\"Value at original pointer: {arrayIntPtr.AsRef()}\"); // Output: Value at original pointer: 1\nConsole.WriteLine($\"Value at offset pointer: {offsetArrayIntPtr.AsRef()}\"); // Output: Value at offset pointer: 3\nConsole.WriteLine($\"Equal? {offsetArrayIntPtr != arrayIntPtr}\"); // Equal? false\n\n// You can also do ++ and --\narrayIntPtr++;\narrayIntPtr++;\n\n// Now arrayIntPtr points to the third element in the array.\n
    "},{"location":"Pointers/Ptr/#value-read-write","title":"Value Read / Write","text":"

    You can read/write values with an implementation of ICanReadWriteMemory

    Reading from RAM:

    int valueFromSource = pointer.Get(); // implicit Memory.Instance\nConsole.WriteLine($\"Value from RAM: {valueFromSource}\");\n

    Reading from RAM of another process:

    // externalMemory = new ExternalMemory(anotherProcess);\nint valueFromSource = pointer.Get(externalMemory);\nConsole.WriteLine($\"Value from another process' RAM: {valueFromSource}\");\n

    You can also read/write to offsets:

    int valueAtOffset2 = pointer.Get(2);\nConsole.WriteLine($\"Value from RAM (Offset 2): {valueAtOffset2}\");\n
    "},{"location":"Pointers/Ptr/#branch-on-null-pointer","title":"Branch on Null Pointer","text":"

    Just like in C, you can branch into an if statement if a pointer isn't null.

    var notNullPointer = new Ptr<int>((int*)0x12345678);\nif (notNullPointer)\nConsole.WriteLine(\"Pointer is not null!\");\n
    "},{"location":"Pointers/Ptr/#from-external-libraries","title":"From External Libraries","text":"

    Getting a ref to native memory/pointer:

    // Defined in a library for modding a certain hoverboard racing game.\npublic static readonly Ptr<int> NumberOfRacers = new Ptr<int>((int*)0x64B758);\n\n// End user can do either\nint* racers = NumberOfRacers;\n\n// or avoid pointer arithmetic entirely.\nref int racers = ref NumberOfRacers.AsRef();\n

    Hooking a function with Reloaded.Hooks:

    // Function pointer declatation (can also use delegate).\n[Function(CallingConventions.MicrosoftThiscall)]\npublic struct OpenFileFnPtr { public FuncPtr<Ptr<byte>, Ptr<byte>, int, Ptr<byte>> Value; }\n\n_openFile = FileSystemFuncs.OpenFile.HookAs<FileSystemFuncs.OpenFileFnPtr>(typeof(FileAccessServer), nameof(OpenBfsFileImpl)).Activate();\n
    "},{"location":"Pointers/Ptr/#sourcedptrt","title":"SourcedPtr<T>","text":"

    This is a tuple of Ptr<T> and TSource.

    Basically, it allows you to assign a TSource to a Ptr<T> and skip passing TSource as a parameter.

    Remaining usage is the same.

    "},{"location":"Reloaded/Readme/","title":"Readme","text":"

    Please visit the documentation site for usage instructions & more.

    "},{"location":"Reloaded/Pages/","title":"Index","text":"The Reloaded MkDocs Theme A Theme for MkDocs Material. That resembles the look of Reloaded."},{"location":"Reloaded/Pages/#about","title":"About","text":"

    This it the NexusMods theme for Material-MkDocs, inspired by the look of Reloaded-II.

    The overall wiki theme should look fairly close to the actual launcher appearance.

    "},{"location":"Reloaded/Pages/#setup-from-scratch","title":"Setup From Scratch","text":"
    • Add this repository as submodule to docs/Reloaded.
    • Save the following configuration as mkdocs.yml in your repository root.
    site_name: Reloaded MkDocs Theme\nsite_url: https://github.com/Reloaded-Project/Reloaded.MkDocsMaterial.Themes.R2\n\nrepo_name: Reloaded-Project/Reloaded.MkDocsMaterial.Themes.R2\nrepo_url: https://github.com/Reloaded-Project/Reloaded.MkDocsMaterial.Themes.R2\n\nextra:\nsocial:\n- icon: fontawesome/brands/github\nlink: https://github.com/Reloaded-Project\n- icon: fontawesome/brands/twitter\nlink: https://twitter.com/thesewer56?lang=en-GB\n\nextra_css:\n- Reloaded/Stylesheets/extra.css\n\nmarkdown_extensions:\n- admonition\n- tables\n- pymdownx.details\n- pymdownx.highlight\n- pymdownx.superfences:\ncustom_fences:\n- name: mermaid\nclass: mermaid\nformat: !!python/name:pymdownx.superfences.fence_code_format\n- pymdownx.tasklist\n- def_list\n- meta\n- md_in_html\n- attr_list\n- footnotes\n- pymdownx.tabbed:\nalternate_style: true\n- pymdownx.emoji:\nemoji_index: !!python/name:materialx.emoji.twemoji\nemoji_generator: !!python/name:materialx.emoji.to_svg\n\ntheme:\nname: material\npalette:\nscheme: reloaded-slate\nfeatures:\n- navigation.instant\n\nplugins:\n- search\n\nnav:\n- Home: index.md\n
    • Add a GitHub Actions workload in .github/workflows/DeployMkDocs.yml.
    name: DeployMkDocs\n\n# Controls when the action will run. \non:\n# Triggers the workflow on push on the master branch\npush:\nbranches: [ main ]\n\n# Allows you to run this workflow manually from the Actions tab\nworkflow_dispatch:\n\n# A workflow run is made up of one or more jobs that can run sequentially or in parallel\njobs:\n# This workflow contains a single job called \"build\"\nbuild:\n# The type of runner that the job will run on\nruns-on: ubuntu-latest\n\n# Steps represent a sequence of tasks that will be executed as part of the job\nsteps:\n\n# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it\n- name: Checkout Branch\nuses: actions/checkout@v2\nwith:\nsubmodules: recursive\n\n# Deploy MkDocs\n- name: Deploy MkDocs\n# You may pin to the exact commit or the version.\n# uses: mhausenblas/mkdocs-deploy-gh-pages@66340182cb2a1a63f8a3783e3e2146b7d151a0bb\nuses: mhausenblas/mkdocs-deploy-gh-pages@master\nenv:\nGITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\nREQUIREMENTS: ./docs/requirements.txt\n
    • Push to GitHub, this should produce a GitHub Pages site.
    • Go to Settings -> Pages in your repo and select gh-pages branch to enable GitHub pages.

    Your page should then be live.

    Tip

    Refer to Contributing for instructions on how to locally edit and modify the wiki.

    Note

    For Reloaded3 theme use reloaded3-slate instead of reloaded-slate.

    "},{"location":"Reloaded/Pages/#extra","title":"Extra","text":"

    Info

    Most documentation pages will also include additional plugins; some which are used in the pages here. Here is a sample complete mkdocs.yml you can copy to your project for reference.

    "},{"location":"Reloaded/Pages/#technical-questions","title":"Technical Questions","text":"

    If you have questions/bug reports/etc. feel free to Open an Issue.

    Happy Documenting \u2764\ufe0f

    "},{"location":"Reloaded/Pages/contributing/","title":"Contributing to the Wiki: Locally","text":"

    Info

    This page shows you how to contribute to any documentation page or wiki based on this template.

    Note

    This theme is forked from my theme for Nexus Docs; and this page is synced with that.

    "},{"location":"Reloaded/Pages/contributing/#tutorial","title":"Tutorial","text":"

    Note

    If you are editing the repository with the theme itself on Windows, it might be a good idea to run git config core.symlinks true first to allow git to create symlinks on clone.

    You should learn the basics of git, an easy way is to give GitHub Desktop (Tutorial) a go. It's only 15 minutes \ud83d\ude00.

    1. Create a GitHub account.
    2. Fork this repository:

      This will create a copy of the repository on your own user account, which you will be able to edit.

    3. Clone this repository.

      For example, using GitHub Desktop:

    4. Make changes inside the docs folder.

      Consider using a Markdown Cheat Sheet if you are new to markdown.

      I recommend using a markdown editor such as Typora. Personally I just work from inside Rider.

    5. Commit the changes and push to GitHub.

    6. Open a Pull Request.

      Opening a Pull Request will allow us to review your changes before adding them with the main official page. If everything's good, we'll hit the merge button and add your changes to the official repository.

    "},{"location":"Reloaded/Pages/contributing/#website-live-preview","title":"Website Live Preview","text":"

    If you are working on the wiki locally, you can generate a live preview the full website. Here's a quick guide of how you could do it from your command prompt (cmd).

    1. Install Python 3

      If you have winget installed, or Windows 11, you can do this from the command prompt.

      winget install Python.Python.3\n

      Otherwise download Python 3 from the official website or package manager.

    2. Install Material for MkDocs and Plugins (Python package)

      # Restart your command prompt before running this command.\npip install mkdocs-material\npip install mkdocs-redirects\n

    3. Open a command prompt in the folder containing mkdocs.yml. and run the site locally.

      # Move to project folder.\ncd <Replace this with full path to folder containing `mkdocs.yml`>\nmkdocs serve\n

      Copy the address to your web browser and enjoy the live preview; any changes you save will be shown instantly.

    "},{"location":"Reloaded/Pages/license/","title":"The Reloaded Project License","text":"

    Most components of the Reloaded are governed by the GPLv3 license.

    In some, albeit rare scenarios, certain libraries might be licensed under LGPLv3 instead.

    This is a FAQ meant to clarify the licensing choice and its implications. Please note, though, that the full license text is the final legal authority.

    "},{"location":"Reloaded/Pages/license/#why-was-gpl-v3-chosen","title":"Why was GPL v3 chosen?","text":"

    The primary objective is to prevent closed-source, commercial exploitation of the project.

    We want to ensure that the project isn't used within a proprietary environment for profit-making purposes such as:

    • Being sold behind a Patreon paywall.
    • Being integrated into a closed-source commercial product for sale.

    The Reloaded Project is a labour of love from unpaid hobbyist volunteers.

    Exploiting that work for profit feels fundamentally unfair.

    While the GPLv3 license doesn't prohibit commercial use outright, it does prevent commercial exploitation by requiring that contributions are given back to the open-source community.

    In that fashion, everyone can benefit from the projects under the Reloaded label.

    "},{"location":"Reloaded/Pages/license/#can-i-use-reloaded-libraries-commercially","title":"Can I use Reloaded Libraries Commercially?","text":"

    You can as long as the resulting produce is also licensed under GPLv3, and thus open source.

    "},{"location":"Reloaded/Pages/license/#can-i-use-reloaded-libraries-in-a-closed-source-application","title":"Can I use Reloaded Libraries in a closed-source application?","text":"

    The license terms do not permit this.

    However, if your software is completely non-commercial, meaning it's neither sold for profit, funded in development, nor hidden behind a paywall (like Patreon), we probably just look the other way.

    This often applies to non-professional programmers, learners, or those with no intent to exploit the project. We believe in understanding and leniency for those who might not know better.

    GPL v3 exists to protect the project and its contributors. If you're not exploiting the project for commercial gain, you're not hurting us; and we will not enforce the terms of the GPL.

    If you are interested in obtaining a commercial license, or want an explicit written exemption, please get in touch with the repository owners.

    "},{"location":"Reloaded/Pages/license/#can-i-link-reloaded-libraries-staticallydynamically","title":"Can I link Reloaded Libraries statically/dynamically?","text":"

    Yes, as long as you adhere to the GPLv3 license terms, you're permitted to statically link Reloaded Libraries into your project, for instance, through the use of NativeAOT or ILMerge.

    "},{"location":"Reloaded/Pages/license/#guidelines-for-non-commercial-use","title":"Guidelines for Non-Commercial Use","text":"

    We support and encourage the non-commercial use of Reloaded Libraries. Non-commercial use generally refers to the usage of our libraries for personal projects, educational purposes, academic research, or use by non-profit organizations.

    "},{"location":"Reloaded/Pages/license/#personal-projects","title":"Personal Projects","text":"

    You're free to use our libraries for projects that you undertake for your own learning, hobby or personal enjoyment. This includes creating mods for your favorite games or building your own applications for personal use.

    "},{"location":"Reloaded/Pages/license/#educational-use","title":"Educational Use","text":"

    Teachers and students are welcome to use our libraries as a learning resource. You can incorporate them into your teaching materials, student projects, coding bootcamps, workshops, etc.

    "},{"location":"Reloaded/Pages/license/#academic-research","title":"Academic Research","text":"

    Researchers may use our libraries for academic and scholarly research. We'd appreciate if you cite our work in any publications that result from research involving our libraries.

    "},{"location":"Reloaded/Pages/license/#non-profit-organizations","title":"Non-profit Organizations","text":"

    If you're part of a registered non-profit organization, you can use our libraries in your projects. However, any derivative work that uses our libraries must also be released under the GPL.

    Please remember, if your usage of our libraries evolves from non-commercial to commercial, you must ensure compliance with the terms of the GPL v3 license.

    "},{"location":"Reloaded/Pages/license/#attribution-requirements","title":"Attribution Requirements","text":"

    As Reloaded Project is a labor of love, done purely out of passion and with an aim to contribute to the broader community, we highly appreciate your support in providing attribution when using our libraries.

    While not legally mandatory under GPL v3, it is a simple act that can go a long way in recognizing the efforts of our contributors and fostering an open and collaborative atmosphere.

    If you choose to provide attribution (and we hope you do!), here are some guidelines:

    • Acknowledge the Use of Reloaded Libraries: Mention that your project uses or is based on Reloaded libraries. This could be in your project's readme, a credits page on a website, a manual, or within the software itself.

    • Link to the Project: If possible, provide a link back to the Reloaded Project. This allows others to explore and potentially benefit from our work.

    Remember, attribution is more than just giving credit,,, it's a way of saying thank you \ud83d\udc49\ud83d\udc48, fostering reciprocal respect, and acknowledging the power of collaborative open-source development.

    We appreciate your support and look forward to seeing what amazing projects you create using Reloaded libraries!

    "},{"location":"Reloaded/Pages/license/#code-from-mitbsd-licensed-projects","title":"Code from MIT/BSD Licensed Projects","text":"

    In some rare instances, code from more permissively licensed projects, such as those under the MIT or BSD licenses, may be referenced, incorporated, or slightly modified within the Reloaded Project.

    It's important to us to respect the terms and intentions of these permissive licenses, which often allow their code to be used in a wide variety of contexts, including in GPL-licensed projects like ours.

    In these cases, the Reloaded Project is committed to clearly disclosing the usage of such code:

    • Method-Level Disclosure: For individual methods or small code snippets, we use appropriate attribution methods, like programming language attributes. For example, methods borrowed or adapted from MIT-licensed projects might be marked with a [MITLicense] attribute.

    • File-Level Disclosure: For larger amounts of code, such as entire files or modules, we'll include the original license text at the top of the file and clearly indicate which portions of the code originate from a differently-licensed project.

    • Project-Level Disclosure: If an entire library or significant portion of a project under a more permissive license is used, we will include an acknowledgment in a prominent location, such as the readme file or the project's license documentation.

    This approach ensures we honor the contributions of the open source community at large, respect the original licenses, and maintain transparency with our users about where code originates from.

    Any files/methods or snippets marked with those attributes may be consumed using their original license terms.

    i.e. If a method is marked with [MITLicense], you may use it under the terms of the MIT license.

    "},{"location":"Reloaded/Pages/license/#contributing-to-the-reloaded-project","title":"Contributing to the Reloaded Project","text":"

    We welcome and appreciate contributions to the Reloaded Project! By contributing, you agree to share your changes under the same GPLv3 license, helping to make the project better for everyone.

    "},{"location":"Reloaded/Pages/testing-zone/","title":"Testing Zone","text":"

    Info

    This is a dummy page with various Material MkDocs controls and features scattered throughout for testing.

    "},{"location":"Reloaded/Pages/testing-zone/#custom-admonitions","title":"Custom Admonitions","text":"

    Reloaded Admonition

    An admonition featuring a Reloaded logo. My source is in Stylesheets/extra.css as Custom 'reloaded' admonition.

    Heart Admonition

    An admonition featuring a heart; because we want to contribute back to the open source community. My source is in Stylesheets/extra.css as Custom 'reloaded heart' admonition.

    Nexus Admonition

    An admonition featuring a Nexus logo. My source is in Stylesheets/extra.css as Custom 'nexus' admonition.

    Heart Admonition

    An admonition featuring a heart; because we want to contribute back to the open source community. My source is in Stylesheets/extra.css as Custom 'nexus heart' admonition.

    "},{"location":"Reloaded/Pages/testing-zone/#mermaid-diagram","title":"Mermaid Diagram","text":"

    Flowchart (Source: Nexus Archive Library):

    flowchart TD\n    subgraph Block 2\n        BigFile1.bin\n    end\n\n    subgraph Block 1\n        BigFile0.bin\n    end\n\n    subgraph Block 0\n        ModConfig.json -.-> Updates.json \n        Updates.json -.-> more[\"... more .json files\"]        \n    end

    Sequence Diagram (Source: Reloaded3 Specification):

    sequenceDiagram\n\n    % Define Items\n    participant Mod Loader\n    participant Virtual FileSystem (VFS)\n    participant CRI CPK Archive Support\n    participant Persona 5 Royal Support\n    participant Joker Costume\n\n    % Define Actions\n    Mod Loader->>Persona 5 Royal Support: Load Mod\n    Persona 5 Royal Support->>Mod Loader: Request CRI CPK Archive Support API\n    Mod Loader->>Persona 5 Royal Support: Receive CRI CPK Archive Support Instance\n\n    Mod Loader->>Joker Costume: Load Mod\n    Mod Loader-->Persona 5 Royal Support: Notification: 'Loaded Joker Costume'\n    Persona 5 Royal Support->>CRI CPK Archive Support: Add Files from 'Joker Costume' to CPK Archive (via API)

    State Diagram (Source: Mermaid Docs):

    stateDiagram-v2\n    [*] --> Still\n    Still --> [*]\n\n    Still --> Moving\n    Moving --> Still\n    Moving --> Crash\n    Crash --> [*]

    Class Diagram (Arbitrary)

    classDiagram\n    class Animal\n    `NexusMobile\u2122` <|-- Car

    Note

    At time of writing, version of Mermaid is a bit outdated here; and other diagrams might not render correctly (even on unmodified theme); thus certain diagrams have been omitted from here.

    "},{"location":"Reloaded/Pages/testing-zone/#code-block","title":"Code Block","text":"

    Snippet from C# version of Sewer's Virtual FileSystem (VFS):

    /// <summary>\n/// Tries to get files for a specific folder, assuming the input path is already in upper case.\n/// </summary>\n/// <param name=\"folderPath\">The folder to find. Already lowercase.</param>\n/// <param name=\"value\">The returned folder instance.</param>\n/// <returns>True if found, else false.</returns>\n[MethodImpl(MethodImplOptions.AggressiveInlining)]\npublic bool TryGetFolderUpper(ReadOnlySpan<char> folderPath, out SpanOfCharDict<TTarget> value)\n{\n// Must be O(1)\nvalue = default!;        // Compare equality.\n// Note to devs: Do not invert branches, we optimise for hot paths here.\nif (folderPath.StartsWith(Prefix))\n{\n// Check for subfolder in branchless way.\n// In CLR, bool is length 1, so conversion to byte should be safe.\n// Even suppose it is not; as long as code is little endian; truncating int/4 bytes to byte still results \n// in correct answer.\nvar hasSubfolder = Prefix.Length != folderPath.Length;\nvar hasSubfolderByte = Unsafe.As<bool, byte>(ref hasSubfolder);\nvar nextFolder = folderPath.SliceFast(Prefix.Length + hasSubfolderByte);\n\nreturn SubfolderToFiles.TryGetValue(nextFolder, out value!);\n}\n\nreturn false;\n}\n

    Something more number heavy, Fast Inverse Square Root from Quake III Arena (unmodified).

    float Q_rsqrt( float number )\n{\nlong i;\nfloat x2, y;\nconst float threehalfs = 1.5F;\n\nx2 = number * 0.5F;\ny  = number;\ni  = * ( long * ) &y;                       // evil floating point bit level hacking\ni  = 0x5f3759df - ( i >> 1 );               // what the fuck? \ny  = * ( float * ) &i;\ny  = y * ( threehalfs - ( x2 * y * y ) );   // 1st iteration\n//  y  = y * ( threehalfs - ( x2 * y * y ) );   // 2nd iteration, this can be removed\n\nreturn y;\n}\n

    "},{"location":"Reloaded/Pages/testing-zone/#default-admonitions","title":"Default Admonitions","text":"

    Note

    Test

    Abstract

    Test

    Info

    Test

    Tip

    Test

    Success

    Test

    Question

    Test

    Warning

    Test

    Failure

    Test

    Danger

    Test

    Bug

    Test

    Example

    Test

    Quote

    Test

    "},{"location":"Reloaded/Pages/testing-zone/#tables","title":"Tables","text":"Method Description GET Fetch resource PUT Update resource DELETE Delete resource"},{"location":"Reloaded/docs/Pages/","title":"Index","text":"The Reloaded MkDocs Theme A Theme for MkDocs Material. That resembles the look of Reloaded."},{"location":"Reloaded/docs/Pages/#about","title":"About","text":"

    This it the NexusMods theme for Material-MkDocs, inspired by the look of Reloaded-II.

    The overall wiki theme should look fairly close to the actual launcher appearance.

    "},{"location":"Reloaded/docs/Pages/#setup-from-scratch","title":"Setup From Scratch","text":"
    • Add this repository as submodule to docs/Reloaded.
    • Save the following configuration as mkdocs.yml in your repository root.
    site_name: Reloaded MkDocs Theme\nsite_url: https://github.com/Reloaded-Project/Reloaded.MkDocsMaterial.Themes.R2\n\nrepo_name: Reloaded-Project/Reloaded.MkDocsMaterial.Themes.R2\nrepo_url: https://github.com/Reloaded-Project/Reloaded.MkDocsMaterial.Themes.R2\n\nextra:\nsocial:\n- icon: fontawesome/brands/github\nlink: https://github.com/Reloaded-Project\n- icon: fontawesome/brands/twitter\nlink: https://twitter.com/thesewer56?lang=en-GB\n\nextra_css:\n- Reloaded/Stylesheets/extra.css\n\nmarkdown_extensions:\n- admonition\n- tables\n- pymdownx.details\n- pymdownx.highlight\n- pymdownx.superfences:\ncustom_fences:\n- name: mermaid\nclass: mermaid\nformat: !!python/name:pymdownx.superfences.fence_code_format\n- pymdownx.tasklist\n- def_list\n- meta\n- md_in_html\n- attr_list\n- footnotes\n- pymdownx.tabbed:\nalternate_style: true\n- pymdownx.emoji:\nemoji_index: !!python/name:materialx.emoji.twemoji\nemoji_generator: !!python/name:materialx.emoji.to_svg\n\ntheme:\nname: material\npalette:\nscheme: reloaded-slate\nfeatures:\n- navigation.instant\n\nplugins:\n- search\n\nnav:\n- Home: index.md\n
    • Add a GitHub Actions workload in .github/workflows/DeployMkDocs.yml.
    name: DeployMkDocs\n\n# Controls when the action will run. \non:\n# Triggers the workflow on push on the master branch\npush:\nbranches: [ main ]\n\n# Allows you to run this workflow manually from the Actions tab\nworkflow_dispatch:\n\n# A workflow run is made up of one or more jobs that can run sequentially or in parallel\njobs:\n# This workflow contains a single job called \"build\"\nbuild:\n# The type of runner that the job will run on\nruns-on: ubuntu-latest\n\n# Steps represent a sequence of tasks that will be executed as part of the job\nsteps:\n\n# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it\n- name: Checkout Branch\nuses: actions/checkout@v2\nwith:\nsubmodules: recursive\n\n# Deploy MkDocs\n- name: Deploy MkDocs\n# You may pin to the exact commit or the version.\n# uses: mhausenblas/mkdocs-deploy-gh-pages@66340182cb2a1a63f8a3783e3e2146b7d151a0bb\nuses: mhausenblas/mkdocs-deploy-gh-pages@master\nenv:\nGITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\nREQUIREMENTS: ./docs/requirements.txt\n
    • Push to GitHub, this should produce a GitHub Pages site.
    • Go to Settings -> Pages in your repo and select gh-pages branch to enable GitHub pages.

    Your page should then be live.

    Tip

    Refer to Contributing for instructions on how to locally edit and modify the wiki.

    Note

    For Reloaded3 theme use reloaded3-slate instead of reloaded-slate.

    "},{"location":"Reloaded/docs/Pages/#extra","title":"Extra","text":"

    Info

    Most documentation pages will also include additional plugins; some which are used in the pages here. Here is a sample complete mkdocs.yml you can copy to your project for reference.

    "},{"location":"Reloaded/docs/Pages/#technical-questions","title":"Technical Questions","text":"

    If you have questions/bug reports/etc. feel free to Open an Issue.

    Happy Documenting \u2764\ufe0f

    "},{"location":"Reloaded/docs/Pages/contributing/","title":"Contributing to the Wiki: Locally","text":"

    Info

    This page shows you how to contribute to any documentation page or wiki based on this template.

    Note

    This theme is forked from my theme for Nexus Docs; and this page is synced with that.

    "},{"location":"Reloaded/docs/Pages/contributing/#tutorial","title":"Tutorial","text":"

    Note

    If you are editing the repository with the theme itself on Windows, it might be a good idea to run git config core.symlinks true first to allow git to create symlinks on clone.

    You should learn the basics of git, an easy way is to give GitHub Desktop (Tutorial) a go. It's only 15 minutes \ud83d\ude00.

    1. Create a GitHub account.
    2. Fork this repository:

      This will create a copy of the repository on your own user account, which you will be able to edit.

    3. Clone this repository.

      For example, using GitHub Desktop:

    4. Make changes inside the docs folder.

      Consider using a Markdown Cheat Sheet if you are new to markdown.

      I recommend using a markdown editor such as Typora. Personally I just work from inside Rider.

    5. Commit the changes and push to GitHub.

    6. Open a Pull Request.

      Opening a Pull Request will allow us to review your changes before adding them with the main official page. If everything's good, we'll hit the merge button and add your changes to the official repository.

    "},{"location":"Reloaded/docs/Pages/contributing/#website-live-preview","title":"Website Live Preview","text":"

    If you are working on the wiki locally, you can generate a live preview the full website. Here's a quick guide of how you could do it from your command prompt (cmd).

    1. Install Python 3

      If you have winget installed, or Windows 11, you can do this from the command prompt.

      winget install Python.Python.3\n

      Otherwise download Python 3 from the official website or package manager.

    2. Install Material for MkDocs and Plugins (Python package)

      # Restart your command prompt before running this command.\npip install mkdocs-material\npip install mkdocs-redirects\n

    3. Open a command prompt in the folder containing mkdocs.yml. and run the site locally.

      # Move to project folder.\ncd <Replace this with full path to folder containing `mkdocs.yml`>\nmkdocs serve\n

      Copy the address to your web browser and enjoy the live preview; any changes you save will be shown instantly.

    "},{"location":"Reloaded/docs/Pages/license/","title":"The Reloaded Project License","text":"

    Most components of the Reloaded are governed by the GPLv3 license.

    In some, albeit rare scenarios, certain libraries might be licensed under LGPLv3 instead.

    This is a FAQ meant to clarify the licensing choice and its implications. Please note, though, that the full license text is the final legal authority.

    "},{"location":"Reloaded/docs/Pages/license/#why-was-gpl-v3-chosen","title":"Why was GPL v3 chosen?","text":"

    The primary objective is to prevent closed-source, commercial exploitation of the project.

    We want to ensure that the project isn't used within a proprietary environment for profit-making purposes such as:

    • Being sold behind a Patreon paywall.
    • Being integrated into a closed-source commercial product for sale.

    The Reloaded Project is a labour of love from unpaid hobbyist volunteers.

    Exploiting that work for profit feels fundamentally unfair.

    While the GPLv3 license doesn't prohibit commercial use outright, it does prevent commercial exploitation by requiring that contributions are given back to the open-source community.

    In that fashion, everyone can benefit from the projects under the Reloaded label.

    "},{"location":"Reloaded/docs/Pages/license/#can-i-use-reloaded-libraries-commercially","title":"Can I use Reloaded Libraries Commercially?","text":"

    You can as long as the resulting produce is also licensed under GPLv3, and thus open source.

    "},{"location":"Reloaded/docs/Pages/license/#can-i-use-reloaded-libraries-in-a-closed-source-application","title":"Can I use Reloaded Libraries in a closed-source application?","text":"

    The license terms do not permit this.

    However, if your software is completely non-commercial, meaning it's neither sold for profit, funded in development, nor hidden behind a paywall (like Patreon), we probably just look the other way.

    This often applies to non-professional programmers, learners, or those with no intent to exploit the project. We believe in understanding and leniency for those who might not know better.

    GPL v3 exists to protect the project and its contributors. If you're not exploiting the project for commercial gain, you're not hurting us; and we will not enforce the terms of the GPL.

    If you are interested in obtaining a commercial license, or want an explicit written exemption, please get in touch with the repository owners.

    "},{"location":"Reloaded/docs/Pages/license/#can-i-link-reloaded-libraries-staticallydynamically","title":"Can I link Reloaded Libraries statically/dynamically?","text":"

    Yes, as long as you adhere to the GPLv3 license terms, you're permitted to statically link Reloaded Libraries into your project, for instance, through the use of NativeAOT or ILMerge.

    "},{"location":"Reloaded/docs/Pages/license/#guidelines-for-non-commercial-use","title":"Guidelines for Non-Commercial Use","text":"

    We support and encourage the non-commercial use of Reloaded Libraries. Non-commercial use generally refers to the usage of our libraries for personal projects, educational purposes, academic research, or use by non-profit organizations.

    "},{"location":"Reloaded/docs/Pages/license/#personal-projects","title":"Personal Projects","text":"

    You're free to use our libraries for projects that you undertake for your own learning, hobby or personal enjoyment. This includes creating mods for your favorite games or building your own applications for personal use.

    "},{"location":"Reloaded/docs/Pages/license/#educational-use","title":"Educational Use","text":"

    Teachers and students are welcome to use our libraries as a learning resource. You can incorporate them into your teaching materials, student projects, coding bootcamps, workshops, etc.

    "},{"location":"Reloaded/docs/Pages/license/#academic-research","title":"Academic Research","text":"

    Researchers may use our libraries for academic and scholarly research. We'd appreciate if you cite our work in any publications that result from research involving our libraries.

    "},{"location":"Reloaded/docs/Pages/license/#non-profit-organizations","title":"Non-profit Organizations","text":"

    If you're part of a registered non-profit organization, you can use our libraries in your projects. However, any derivative work that uses our libraries must also be released under the GPL.

    Please remember, if your usage of our libraries evolves from non-commercial to commercial, you must ensure compliance with the terms of the GPL v3 license.

    "},{"location":"Reloaded/docs/Pages/license/#attribution-requirements","title":"Attribution Requirements","text":"

    As Reloaded Project is a labor of love, done purely out of passion and with an aim to contribute to the broader community, we highly appreciate your support in providing attribution when using our libraries.

    While not legally mandatory under GPL v3, it is a simple act that can go a long way in recognizing the efforts of our contributors and fostering an open and collaborative atmosphere.

    If you choose to provide attribution (and we hope you do!), here are some guidelines:

    • Acknowledge the Use of Reloaded Libraries: Mention that your project uses or is based on Reloaded libraries. This could be in your project's readme, a credits page on a website, a manual, or within the software itself.

    • Link to the Project: If possible, provide a link back to the Reloaded Project. This allows others to explore and potentially benefit from our work.

    Remember, attribution is more than just giving credit,,, it's a way of saying thank you \ud83d\udc49\ud83d\udc48, fostering reciprocal respect, and acknowledging the power of collaborative open-source development.

    We appreciate your support and look forward to seeing what amazing projects you create using Reloaded libraries!

    "},{"location":"Reloaded/docs/Pages/license/#code-from-mitbsd-licensed-projects","title":"Code from MIT/BSD Licensed Projects","text":"

    In some rare instances, code from more permissively licensed projects, such as those under the MIT or BSD licenses, may be referenced, incorporated, or slightly modified within the Reloaded Project.

    It's important to us to respect the terms and intentions of these permissive licenses, which often allow their code to be used in a wide variety of contexts, including in GPL-licensed projects like ours.

    In these cases, the Reloaded Project is committed to clearly disclosing the usage of such code:

    • Method-Level Disclosure: For individual methods or small code snippets, we use appropriate attribution methods, like programming language attributes. For example, methods borrowed or adapted from MIT-licensed projects might be marked with a [MITLicense] attribute.

    • File-Level Disclosure: For larger amounts of code, such as entire files or modules, we'll include the original license text at the top of the file and clearly indicate which portions of the code originate from a differently-licensed project.

    • Project-Level Disclosure: If an entire library or significant portion of a project under a more permissive license is used, we will include an acknowledgment in a prominent location, such as the readme file or the project's license documentation.

    This approach ensures we honor the contributions of the open source community at large, respect the original licenses, and maintain transparency with our users about where code originates from.

    Any files/methods or snippets marked with those attributes may be consumed using their original license terms.

    i.e. If a method is marked with [MITLicense], you may use it under the terms of the MIT license.

    "},{"location":"Reloaded/docs/Pages/license/#contributing-to-the-reloaded-project","title":"Contributing to the Reloaded Project","text":"

    We welcome and appreciate contributions to the Reloaded Project! By contributing, you agree to share your changes under the same GPLv3 license, helping to make the project better for everyone.

    "},{"location":"Reloaded/docs/Pages/testing-zone/","title":"Testing Zone","text":"

    Info

    This is a dummy page with various Material MkDocs controls and features scattered throughout for testing.

    "},{"location":"Reloaded/docs/Pages/testing-zone/#custom-admonitions","title":"Custom Admonitions","text":"

    Reloaded Admonition

    An admonition featuring a Reloaded logo. My source is in Stylesheets/extra.css as Custom 'reloaded' admonition.

    Heart Admonition

    An admonition featuring a heart; because we want to contribute back to the open source community. My source is in Stylesheets/extra.css as Custom 'reloaded heart' admonition.

    Nexus Admonition

    An admonition featuring a Nexus logo. My source is in Stylesheets/extra.css as Custom 'nexus' admonition.

    Heart Admonition

    An admonition featuring a heart; because we want to contribute back to the open source community. My source is in Stylesheets/extra.css as Custom 'nexus heart' admonition.

    "},{"location":"Reloaded/docs/Pages/testing-zone/#mermaid-diagram","title":"Mermaid Diagram","text":"

    Flowchart (Source: Nexus Archive Library):

    flowchart TD\n    subgraph Block 2\n        BigFile1.bin\n    end\n\n    subgraph Block 1\n        BigFile0.bin\n    end\n\n    subgraph Block 0\n        ModConfig.json -.-> Updates.json \n        Updates.json -.-> more[\"... more .json files\"]        \n    end

    Sequence Diagram (Source: Reloaded3 Specification):

    sequenceDiagram\n\n    % Define Items\n    participant Mod Loader\n    participant Virtual FileSystem (VFS)\n    participant CRI CPK Archive Support\n    participant Persona 5 Royal Support\n    participant Joker Costume\n\n    % Define Actions\n    Mod Loader->>Persona 5 Royal Support: Load Mod\n    Persona 5 Royal Support->>Mod Loader: Request CRI CPK Archive Support API\n    Mod Loader->>Persona 5 Royal Support: Receive CRI CPK Archive Support Instance\n\n    Mod Loader->>Joker Costume: Load Mod\n    Mod Loader-->Persona 5 Royal Support: Notification: 'Loaded Joker Costume'\n    Persona 5 Royal Support->>CRI CPK Archive Support: Add Files from 'Joker Costume' to CPK Archive (via API)

    State Diagram (Source: Mermaid Docs):

    stateDiagram-v2\n    [*] --> Still\n    Still --> [*]\n\n    Still --> Moving\n    Moving --> Still\n    Moving --> Crash\n    Crash --> [*]

    Class Diagram (Arbitrary)

    classDiagram\n    class Animal\n    `NexusMobile\u2122` <|-- Car

    Note

    At time of writing, version of Mermaid is a bit outdated here; and other diagrams might not render correctly (even on unmodified theme); thus certain diagrams have been omitted from here.

    "},{"location":"Reloaded/docs/Pages/testing-zone/#code-block","title":"Code Block","text":"

    Snippet from C# version of Sewer's Virtual FileSystem (VFS):

    /// <summary>\n/// Tries to get files for a specific folder, assuming the input path is already in upper case.\n/// </summary>\n/// <param name=\"folderPath\">The folder to find. Already lowercase.</param>\n/// <param name=\"value\">The returned folder instance.</param>\n/// <returns>True if found, else false.</returns>\n[MethodImpl(MethodImplOptions.AggressiveInlining)]\npublic bool TryGetFolderUpper(ReadOnlySpan<char> folderPath, out SpanOfCharDict<TTarget> value)\n{\n// Must be O(1)\nvalue = default!;        // Compare equality.\n// Note to devs: Do not invert branches, we optimise for hot paths here.\nif (folderPath.StartsWith(Prefix))\n{\n// Check for subfolder in branchless way.\n// In CLR, bool is length 1, so conversion to byte should be safe.\n// Even suppose it is not; as long as code is little endian; truncating int/4 bytes to byte still results \n// in correct answer.\nvar hasSubfolder = Prefix.Length != folderPath.Length;\nvar hasSubfolderByte = Unsafe.As<bool, byte>(ref hasSubfolder);\nvar nextFolder = folderPath.SliceFast(Prefix.Length + hasSubfolderByte);\n\nreturn SubfolderToFiles.TryGetValue(nextFolder, out value!);\n}\n\nreturn false;\n}\n

    Something more number heavy, Fast Inverse Square Root from Quake III Arena (unmodified).

    float Q_rsqrt( float number )\n{\nlong i;\nfloat x2, y;\nconst float threehalfs = 1.5F;\n\nx2 = number * 0.5F;\ny  = number;\ni  = * ( long * ) &y;                       // evil floating point bit level hacking\ni  = 0x5f3759df - ( i >> 1 );               // what the fuck? \ny  = * ( float * ) &i;\ny  = y * ( threehalfs - ( x2 * y * y ) );   // 1st iteration\n//  y  = y * ( threehalfs - ( x2 * y * y ) );   // 2nd iteration, this can be removed\n\nreturn y;\n}\n

    "},{"location":"Reloaded/docs/Pages/testing-zone/#default-admonitions","title":"Default Admonitions","text":"

    Note

    Test

    Abstract

    Test

    Info

    Test

    Tip

    Test

    Success

    Test

    Question

    Test

    Warning

    Test

    Failure

    Test

    Danger

    Test

    Bug

    Test

    Example

    Test

    Quote

    Test

    "},{"location":"Reloaded/docs/Pages/testing-zone/#tables","title":"Tables","text":"Method Description GET Fetch resource PUT Update resource DELETE Delete resource"},{"location":"Streams/BufferedStreamReader/","title":"BufferedStreamReader Class","text":"

    The BufferedStreamReader is a buffering mechanism for reading data from streams, allowing for fast reading of data while preserving stream-like semantics.

    BufferedStreamReader is a high-performance replacement for BinaryReader with minimal error checking.

    BufferedStreamReader is not thread-safe.

    BufferedStreamReader cannot read values larger than buffer size it was initialised with.

    BufferedStreamReader has minimal error checking at runtime.

    Tip

    Remember, always ensure the stream and reader are properly disposed of after use. The best practice is to use the using statement or try-finally block in C# to ensure resources are correctly released.

    "},{"location":"Streams/BufferedStreamReader/#performance","title":"Performance","text":"

    Amount of time taken to read 8 MiB of data (library version 9.0.0):

    Legend: - BinaryReader read via BinaryReader. - BufferedStreamReader read via BufferedStreamReader. - BufferedStreamReader read via BufferedStreamReader (ReadRaw method). - NativePointer no stream; no copy; access existing data from array (baseline reference).

    "},{"location":"Streams/BufferedStreamReader/#memorystream","title":"MemoryStream","text":"

    Benchmarks on MemoryStream (near zero overhead) allow us to compare the performance against BinaryReader and array access (baseline reference).

    Byte:

    Method Mean Code Size BinaryReader 15,452.7 us 171 B BufferedStreamReader 6,298.7 us 703 B BufferedStreamReader Raw 1,997.3 us 669 B NativePointer 1,845.2 us 38 B

    Int:

    Method Mean Code Size BinaryReader 3,253.2 us 637 B BufferedStreamReader 1,708.7 us 981 B BufferedStreamReader Raw 606.8 us 760 B NativePointer 464.1 us 54 B

    Long:

    Method Mean Code Size BinaryReader 1,665.2 us 639 B BufferedStreamReader 890.8 us 709 B BufferedStreamReader Raw 370.7 us 761 B NativePointer 227.3 us 55 B"},{"location":"Streams/BufferedStreamReader/#filestream","title":"FileStream","text":"

    Benchmarks on FileStream allow us to compare the performance against BinaryReader more closely.

    Byte:

    Method Mean Code Size BinaryReader 21,309.7 us 169 B BufferedStreamReader 6,731.9 us 1,052 B BufferedStreamReader Raw 2,763.3 us 661 B

    Int:

    Method Mean Code Size BinaryReader 22,279.2 us 640 B BufferedStreamReader 2,219.4 us 1,487 B BufferedStreamReader Raw 1,310.4 us 753 B

    Long:

    Method Mean Code Size BinaryReader 13,025.8 us 642 B BufferedStreamReader 1,425.6 us 1,068 B BufferedStreamReader Raw 943.7 us 754 B"},{"location":"Streams/BufferedStreamReader/#properties","title":"Properties","text":"
    • BaseStream: The stream this class was instantiated with.
    • BufferBytesAvailable: The remaining number of bytes that are currently buffered.
    • CurrentBufferSize: The total size of the current buffered data at this moment in time.
    • IsEndOfStream: This is true if end of stream was reached while refilling the internal buffer.
    • OnEndOfStream: This method is executed if a buffer refill does not fill the whole buffer, indicating end of stream was reached.
    "},{"location":"Streams/BufferedStreamReader/#constructors","title":"Constructors","text":"
    • BufferedStreamReader(TStream stream, int bufferSize = 65536): Constructs a BufferedStreamReader.
    "},{"location":"Streams/BufferedStreamReader/#methods","title":"Methods","text":"

    Just like with regular Stream APIs, less data can be returned than requested if end of stream was reached. Please note BufferedStreamReader does not throw in these scenarios.

    "},{"location":"Streams/BufferedStreamReader/#seek","title":"Seek","text":"
    public void Seek(long offset, SeekOrigin origin)\n

    Seeks the underlying stream to a specified position.

    "},{"location":"Streams/BufferedStreamReader/#advance","title":"Advance","text":"
    public void Advance(long offset)\n

    Advances the underlying stream by a specified number of bytes. (This is equivalent to Seek(offset, SeekOrigin.Current))

    "},{"location":"Streams/BufferedStreamReader/#read","title":"Read","text":"
    public T Read<T>() where T : unmanaged\npublic void Read<T>(out T value) where T : unmanaged\n

    Reads an unmanaged, generic type from the stream.

    "},{"location":"Streams/BufferedStreamReader/#readraw","title":"ReadRaw","text":"

    The returned values point to internal buffers. DO NOT MODIFY THE DATA!

    public byte* ReadRaw(int length, out int available)\npublic T* ReadRaw<T>(int numItems, out int available) where T : unmanaged\n

    Provides a pointer to the buffered data; buffering sufficient data if needed.

    "},{"location":"Streams/BufferedStreamReader/#readraw-with-output","title":"ReadRaw (with Output)","text":"

    Variant of ReadRaw that copies the data to user's own destination.

    public int ReadRaw<T>(Span<T> buffer) where T : unmanaged\npublic int ReadRaw<T>(T* buffer, int numItems) where T : unmanaged\n

    Reads raw data from the stream, without conversion. The output is written to the supplied pointer or span.

    "},{"location":"Streams/BufferedStreamReader/#readbytesunbuffered","title":"ReadBytesUnbuffered","text":"

    This method is useful for reading large blobs (e.g. a compressed file from an archive) without discarding the buffered data.

    public int ReadBytesUnbuffered(long offset, Span<byte> data)\n

    Reads a specified amount of bytes at a specific offset from the underlying stream without resetting the buffers or advancing the read pointer.

    "},{"location":"Streams/BufferedStreamReader/#readmarshalled","title":"ReadMarshalled","text":"
    public T ReadMarshalled<T>()\n

    Reads a value that requires marshalling from the stream.

    "},{"location":"Streams/BufferedStreamReader/#peek","title":"Peek","text":"
    public T Peek<T>() where T : unmanaged\npublic void Peek<T>(out T value) where T : unmanaged\n

    Reads an unmanaged, generic type from the stream without incrementing the position.

    "},{"location":"Streams/BufferedStreamReader/#peekmarshalled","title":"PeekMarshalled","text":"
    public T PeekMarshalled<T>()\npublic void PeekMarshalled<T>(out T value)\n

    Reads a value that requires marshalling from the stream without advancing the position.

    "},{"location":"Streams/BufferedStreamReader/#methods-endian-extensions","title":"Methods (Endian Extensions)","text":""},{"location":"Streams/BufferedStreamReader/#peeklittleendian","title":"PeekLittleEndian","text":"
    public Int16 PeekLittleEndianInt16()\npublic Int16 PeekLittleEndian(out Int16 value)\npublic UInt16 PeekLittleEndianUInt16()\npublic UInt16 PeekLittleEndian(out UInt16 value)\npublic Int32 PeekLittleEndianInt32()\npublic Int32 PeekLittleEndian(out Int32 value)\npublic UInt32 PeekLittleEndianUInt32()\npublic UInt32 PeekLittleEndian(out UInt32 value)\npublic Int64 PeekLittleEndianInt64()\npublic Int64 PeekLittleEndian(out Int64 value)\npublic UInt64 PeekLittleEndianUInt64()\npublic UInt64 PeekLittleEndian(out UInt64 value)\npublic Single PeekLittleEndianSingle()\npublic Single PeekLittleEndian(out Single value)\npublic Double PeekLittleEndianDouble()\npublic Double PeekLittleEndian(out Double value)\n

    Peeks a little endian value of the specified type from the stream without incrementing the position.

    "},{"location":"Streams/BufferedStreamReader/#peekbigendian","title":"PeekBigEndian","text":"
    public Int16 PeekBigEndianInt16()\npublic Int16 PeekBigEndian(out Int16 value)\npublic UInt16 PeekBigEndianUInt16()\npublic UInt16 PeekBigEndian(out UInt16 value)\npublic Int32 PeekBigEndianInt32()\npublic Int32 PeekBigEndian(out Int32 value)\npublic UInt32 PeekBigEndianUInt32()\npublic UInt32 PeekBigEndian(out UInt32 value)\npublic Int64 PeekBigEndianInt64()\npublic Int64 PeekBigEndian(out Int64 value)\npublic UInt64 PeekBigEndianUInt64()\npublic UInt64 PeekBigEndian(out UInt64 value)\npublic Single PeekBigEndianSingle()\npublic Single PeekBigEndian(out Single value)\npublic Double PeekBigEndianDouble()\npublic Double PeekBigEndian(out Double value)\n

    Peeks a big endian value of the specified type from the stream without incrementing the position.

    "},{"location":"Streams/BufferedStreamReader/#readlittleendian","title":"ReadLittleEndian","text":"
    public Int16 ReadLittleEndianInt16()\npublic Int16 ReadLittleEndian(out Int16 value)\npublic UInt16 ReadLittleEndianUInt16()\npublic UInt16 ReadLittleEndian(out UInt16 value)\npublic Int32 ReadLittleEndianInt32()\npublic Int32 ReadLittleEndian(out Int32 value)\npublic UInt32 ReadLittleEndianUInt32()\npublic UInt32 ReadLittleEndian(out UInt32 value)\npublic Int64 ReadLittleEndianInt64()\npublic Int64 ReadLittleEndian(out Int64 value)\npublic UInt64 ReadLittleEndianUInt64()\npublic UInt64 ReadLittleEndian(out UInt64 value)\npublic Single ReadLittleEndianSingle()\npublic Single ReadLittleEndian(out Single value)\npublic Double ReadLittleEndianDouble()\npublic Double ReadLittleEndian(out Double value)\n

    Reads a little endian value of the specified type from the stream and advances the position by the size of the type.

    "},{"location":"Streams/BufferedStreamReader/#readbigendian","title":"ReadBigEndian","text":"
    public Int16 ReadBigEndianInt16()\npublic Int16 ReadBigEndian(out Int16 value)\npublic UInt16 ReadBigEndianUInt16()\npublic UInt16 ReadBigEndian(out UInt16 value)\npublic Int32 ReadBigEndianInt32()\npublic Int32 ReadBigEndian(out Int32 value)\npublic UInt32 ReadBigEndianUInt32()\npublic UInt32 ReadBigEndian(out UInt32 value)\npublic Int64 ReadBigEndianInt64()\npublic Int64 ReadBigEndian(out Int64 value)\npublic UInt64 ReadBigEndianUInt64()\npublic UInt64 ReadBigEndian(out UInt64 value)\npublic Single ReadBigEndianSingle()\npublic Single ReadBigEndian(out Single value)\npublic Double ReadBigEndianDouble()\npublic Double ReadBigEndian(out Double value)\n

    Reads a big endian value of the specified type from the stream and advances the position by the size of the type.

    "},{"location":"Streams/BufferedStreamReader/#aslittleendian","title":"AsLittleEndian","text":"

    Implements, IEndianedBufferStreamReader<TStream>. Use constraint where T : IEndianedBufferStreamReader<TStream> to write endian agnostic code without any overhead.

    public LittleEndianBufferedStreamReader<TStream> AsLittleEndian();\n

    Returns a reader that can be used to read little endian values from the stream.

    "},{"location":"Streams/BufferedStreamReader/#asbigendian","title":"AsBigEndian","text":"

    Implements, IEndianedBufferStreamReader<TStream>. Use constraint where T : IEndianedBufferStreamReader<TStream> to write endian agnostic code without any overhead.

    public BigEndianBufferedStreamReader<TStream> AsBigEndian();\n

    Returns a reader that can be used to read big endian values from the stream.

    "},{"location":"Streams/BufferedStreamReader/#methods-endian-struct-extensions","title":"Methods (Endian Struct Extensions)","text":"

    The following methods are valid for structs which implement ICanReverseEndian

    "},{"location":"Streams/BufferedStreamReader/#peeklittleendianstruct","title":"PeekLittleEndianStruct","text":"
    public T PeekLittleEndianStruct<T>() where T : unmanaged, ICanReverseEndian\npublic void PeekLittleEndianStruct<T>(out T value) where T : unmanaged, ICanReverseEndian\n

    Peeks a little endian unmanaged, generic type from the stream without incrementing the position.

    "},{"location":"Streams/BufferedStreamReader/#peekbigendianstruct","title":"PeekBigEndianStruct","text":"
    public T PeekBigEndianStruct<T>() where T : unmanaged, ICanReverseEndian\npublic void PeekBigEndianStruct<T>(out T value) where T : unmanaged, ICanReverseEndian\n

    Peeks a big endian unmanaged, generic type from the stream without incrementing the position.

    "},{"location":"Streams/BufferedStreamReader/#readlittleendianstruct","title":"ReadLittleEndianStruct","text":"
    public T ReadLittleEndianStruct<T>() where T : unmanaged, ICanReverseEndian\npublic void ReadLittleEndianStruct<T>(out T value) where T : unmanaged, ICanReverseEndian\n

    Reads a little endian unmanaged, generic type from the stream.

    "},{"location":"Streams/BufferedStreamReader/#readbigendianstruct","title":"ReadBigEndianStruct","text":"
    public T ReadBigEndianStruct<T>() where T : unmanaged, ICanReverseEndian\npublic void ReadBigEndianStruct<T>(out T value) where T : unmanaged, ICanReverseEndian\n

    Reads a big endian unmanaged, generic type from the stream.

    "},{"location":"Streams/BufferedStreamReader/#examples","title":"Examples","text":""},{"location":"Streams/BufferedStreamReader/#creating-a-bufferedstreamreader","title":"Creating a BufferedStreamReader","text":"
    var stream = File.OpenRead(\"myFile.txt\");\nusing var reader = new BufferedStreamReader<FileStream>(stream);\n
    "},{"location":"Streams/BufferedStreamReader/#reading-an-integer-from-the-stream","title":"Reading an Integer from the Stream","text":"
    int value = reader.Read<int>();\nConsole.WriteLine($\"Read value: {value}\");\n
    "},{"location":"Streams/BufferedStreamReader/#reading-raw-bytes","title":"Reading Raw Bytes","text":"

    Do not modify the returned data! Copy it elsewhere first!

    int length = 10;\nint available;\nbyte* rawBytes = reader.ReadRaw(length, out available);\n
    "},{"location":"Streams/BufferedStreamReader/#reading-raw-structs","title":"Reading Raw Structs","text":"
    using var reader = new BufferedStreamReader<FileStream>(fileStream);\nSpan<Vector3> span = stackalloc Vector3[10];\nint readItems = reader.ReadRaw(span);\n\nConsole.WriteLine($\"{readItems} Vector3 items were read from the stream.\");\n

    In this example, we create a BufferedStreamReader using a FileStream and then declare a Span<Vector3> where Vector3 is a struct representing a 3D vector. We then read from the stream directly into the Span<Vector3>. After reading, we print out how many Vector3 items were read from the stream.

    "},{"location":"Streams/BufferedStreamReader/#seeking-and-advancing-stream","title":"Seeking and Advancing Stream","text":"
    var reader = new BufferedStreamReader<FileStream>(fileStream);\nreader.Seek(100, SeekOrigin.Begin); // Seek to 100 bytes from the start\nreader.Advance(50); // Advance 50 bytes from the current position\n\nConsole.WriteLine($\"Current stream position is {reader.Position()}\");\n

    In this example, we first seek to 100 bytes from the start of the stream. Then we advance 50 bytes from the current position. After that, we print out the current stream position.

    "},{"location":"Streams/BufferedStreamReader/#reading-unmanaged-types","title":"Reading Unmanaged Types","text":"
    using var reader = new BufferedStreamReader<FileStream>(fileStream);\nint value = reader.Read<int>(); // Reads an integer from the stream\n\nConsole.WriteLine($\"The read integer value is {value}\");\n

    In this example, we read an integer directly from the stream and print it out.

    "},{"location":"Streams/BufferedStreamReader/#reading-large-raw-data","title":"Reading Large Raw Data","text":"
    using var reader = new BufferedStreamReader<FileStream>(fileStream);\nSpan<byte> dataSpan = stackalloc byte[1024];\nint bytesRead = reader.ReadBytesUnbuffered(200, dataSpan);\n\nConsole.WriteLine($\"{bytesRead} bytes were read from the stream.\");\n

    In this example, we read 1024 bytes starting from 200 bytes offset into a Span<byte> without resetting the buffers or advancing the read pointer. After reading, we print out how many bytes were read from the stream.

    Value of bytesRead may be less than length of dataSpan if end of stream was reached.

    "},{"location":"Streams/BufferedStreamReader/#peeking-data","title":"Peeking Data","text":"
    using var reader = new BufferedStreamReader<FileStream>(fileStream);\nint value = reader.Peek<int>(); // Peeks an integer from the stream\n\nConsole.WriteLine($\"The peeked integer value is {value}. Stream did not advance.\");\n
    "},{"location":"Streams/BufferedStreamReader/#using-customized-buffer-size","title":"Using Customized Buffer Size","text":"

    The default buffer size of 64KBytes should be sufficient for most use cases, including file reads.

    int bufferSize = 8192; // 8 KB\nusing var reader = new BufferedStreamReader<FileStream>(fileStream, bufferSize);\n\nConsole.WriteLine($\"Custom buffer size of {bufferSize} bytes is used for the reader.\");\n

    In this example, a custom buffer size is set when creating a BufferedStreamReader. This allows you to tune the buffer size to match your specific use case, potentially improving performance.

    "},{"location":"Streams/BufferedStreamReader/#combining-multiple-operations","title":"Combining Multiple Operations","text":"
    var reader = new BufferedStreamReader<FileStream>(fileStream);\nreader.Seek(100, SeekOrigin.Begin); int value = reader.Read<int>(); reader.Advance(50); Vector3 vector = reader.Read<Vector3>();\n\nConsole.WriteLine($\"Read integer value: {value}, Vector3: {vector.X}, {vector.Y}, {vector.Z}.\");\n

    In this final example, multiple operations are combined. First, the reader seeks to a specific position in the stream. Then, an integer is read, the reader advances a certain number of bytes, and finally, a Vector3 struct is read. The results are then printed to the console.

    "},{"location":"Streams/BufferedStreamReader/#examples-extensions","title":"Examples (Extensions)","text":""},{"location":"Streams/BufferedStreamReader/#writing-endian-agnostic-code","title":"Writing Endian Agnostic Code","text":"

    Shows you how to write code that works with both Big and Little Endian data.

    using var reader = new BufferedStreamReader<FileStream>(fileStream);\n\n// Read in Big Endian\nRead(reader.AsBigEndian());\n// or... as Little Endian\nRead(reader.AsLittleEndian());\n\nprivate void Read<TReader>(TReader reader) where TReader : IEndianedBufferStreamReader\n{\n// Some neat parsing code here.\nvar i16 = reader.ReadInt16();\nvar i32 = reader.PeekInt32();\n}\n

    This approach allows you to write code which uses the same logic for both big and little endian. You can either pass reader.AsLittleEndian() or reader.AsBigEndian() to your parsing code. Either way, your reader will be devirtualized and you'll be able to parse away with 0 overhead.

    "},{"location":"Streams/BufferedStreamReader/#reading-biglittle-endian-primitives","title":"Reading Big/Little Endian Primitives","text":"
    using var reader = new BufferedStreamReader<FileStream>(fileStream);\n\n// Little Endian\nInt16 littleEndianInt16 = reader.PeekLittleEndianInt16();\nConsole.WriteLine($\"The read Int16 value at offset 0 in Little Endian is {littleEndianInt16}\");\n\n// Big Endian\nInt16 bigEndianInt16 = reader.PeekBigEndianInt16();\nConsole.WriteLine($\"The read Int16 value at offset 0 in Big Endian is {bigEndianInt16}\");\n
    "},{"location":"Streams/BufferedStreamReader/#examples-endian-struct-extensions","title":"Examples (Endian Struct Extensions)","text":"

    CustomStruct must implement ICanReverseEndian

    Example:

    public struct CustomStruct : ICanReverseEndian\n{\npublic int Value1;\npublic int Value2;\npublic int Value3;\n\n// ICanReverseEndian\npublic void ReverseEndian()\n{\nValue1 = Endian.Reverse(Value1);\nValue2 = Endian.Reverse(Value2);\nValue3 = Endian.Reverse(Value3);\n}\n}\n
    "},{"location":"Streams/BufferedStreamReader/#reading-a-little-endian-struct","title":"Reading a Little Endian Struct","text":"
    using var reader = new BufferedStreamReader<FileStream>(fileStream);\nvar value = reader.ReadLittleEndianStruct<CustomStruct>();\n\nConsole.WriteLine($\"The read CustomStruct value is {value}\");\n

    In this example, a CustomStruct is read directly from the stream using little endian byte order.

    "},{"location":"Streams/BufferedStreamReader/#reading-a-big-endian-struct","title":"Reading a Big Endian Struct","text":"
    using var reader = new BufferedStreamReader<FileStream>(fileStream);\nvar value = reader.ReadBigEndianStruct<CustomStruct>();\n\nConsole.WriteLine($\"The read CustomStruct value is {value}\");\n

    In this example, a CustomStruct is read directly from the stream using big endian byte order.

    "},{"location":"Streams/BufferedStreamReader/#peeking-a-little-endian-struct","title":"Peeking a Little Endian Struct","text":"
    using var reader = new BufferedStreamReader<FileStream>(fileStream);\nvar value = reader.PeekLittleEndianStruct<CustomStruct>();\n\nConsole.WriteLine($\"The peeked CustomStruct value is {value}. Stream did not advance.\");\n

    In this example, a CustomStruct is peeked from the stream without advancing the stream position, using little endian byte order.

    "},{"location":"Streams/BufferedStreamReader/#peeking-a-big-endian-struct","title":"Peeking a Big Endian Struct","text":"
    using var reader = new BufferedStreamReader<FileStream>(fileStream);\nvar value = reader.PeekBigEndianStruct<CustomStruct>();\n\nConsole.WriteLine($\"The peeked CustomStruct value is {value}. Stream did not advance.\");\n

    In this example, a CustomStruct is peeked from the stream without advancing the stream position, using big endian byte order.

    CustomStruct must be an unmanaged type and implement ICanReverseEndian interface.

    "},{"location":"Streams/EndianReaders/About/","title":"About","text":"

    Common Info About Endian Readers and Writers

    "},{"location":"Streams/EndianReaders/About/#interfaces","title":"Interfaces","text":"

    Structs can implement ICanBeReadByAnEndianReader and ICanWriteToAnEndianWriter to allow for easy reading and writing.

    Example:

    "},{"location":"Streams/EndianReaders/About/#about-the-offset-methods","title":"About the Offset Methods","text":"

    The structs provide methods named WriteAtOffset / ReadAtOffset to operate on an offset of the current pointer without advancing the pointer itself.

    These methods offer some minor performance advantages.

    "},{"location":"Streams/EndianReaders/About/#improved-pipelining","title":"Improved Pipelining","text":"

    By reducing the dependency of future instructions on earlier instructions, these offset methods allow for better pipelining. For example, a future read operation does not need to wait for the Ptr value to be updated from a previous operation.

    "},{"location":"Streams/EndianReaders/About/#jit-optimization","title":"JIT Optimization","text":"

    The Just-In-Time (JIT) compiler can recognize when the offset parameters are specified as constants and can optimize the instructions accordingly. This can lead to more efficient code execution.

    writer.WriteAtOffset(Hash, 0);\nwriter.WriteAtOffset((int)DecompressedSize, 8);\nwriter.WriteAtOffset(new OffsetPathIndexTuple(DecompressedBlockOffset, FilePathIndex, FirstBlockIndex).Data, 12);\nwriter.Seek(NativeFileEntryV0.SizeBytes);\n

    Because write on line 1, does not depend on modified pointer after line 0, execution is faster, as the CPU can better pipeline the instructions as there is no dependency on the ptr result of the previous method call.

    "},{"location":"Streams/EndianReaders/BigEndianReader/","title":"BigEndianReader","text":"

    A struct for reading from a pointer in Big Endian.

    BigEndianReader is preferred over BufferedStreamReader when all data is already in memory.

    The BigEndianReader struct provides utility methods for reading various data types from a pointer in Big Endian format.

    "},{"location":"Streams/EndianReaders/BigEndianReader/#methods","title":"Methods","text":""},{"location":"Streams/EndianReaders/BigEndianReader/#read-methods","title":"Read Methods","text":"

    These methods read the specified data type from the current pointer in Big Endian format and advance the pointer.

    public byte ReadByte()\npublic sbyte ReadSByte()\npublic short ReadShort()\npublic ushort ReadUShort()\npublic uint ReadUInt()\npublic int ReadInt()\npublic ulong ReadULong()\npublic long ReadLong()\npublic float ReadFloat()\npublic double ReadDouble()\n
    "},{"location":"Streams/EndianReaders/BigEndianReader/#readatoffset-methods","title":"ReadAtOffset Methods","text":"

    These methods read the specified data type from the specified offset in Big Endian format without advancing the pointer.

    public byte ReadByteAtOffset(int offset)\npublic sbyte ReadSByteAtOffset(int offset)\npublic short ReadShortAtOffset(int offset)\npublic ushort ReadUShortAtOffset(int offset)\npublic uint ReadUIntAtOffset(int offset)\npublic int ReadIntAtOffset(int offset)\npublic ulong ReadULongAtOffset(int offset)\npublic long ReadLongAtOffset(int offset)\npublic float ReadFloatAtOffset(int offset)\npublic double ReadDoubleAtOffset(int offset)\n
    "},{"location":"Streams/EndianReaders/BigEndianReader/#seek-method","title":"Seek Method","text":"

    This method advances the pointer by a specified number of bytes.

    public void Seek(int offset)\n
    "},{"location":"Streams/EndianReaders/BigEndianReader/#about-the-offset-methods","title":"About the Offset Methods","text":"

    The BigEndianReader struct provides several methods that read from a specific offset without advancing the pointer. These methods include ReadShortAtOffset, ReadIntAtOffset, ReadLongAtOffset, and ReadUlongAtOffset.

    While these methods do not significantly reduce the instruction count, they offer some minor performance advantages, you can read more about this in About Section

    "},{"location":"Streams/EndianReaders/BigEndianReader/#usage","title":"Usage","text":""},{"location":"Streams/EndianReaders/BigEndianReader/#reading-from-pointer","title":"Reading from Pointer","text":"
    BigEndianReader reader = new BigEndianReader(GetPointer());\n\nbyte byteValue = reader.ReadByte();\nuint uintValue = reader.ReadUInt();\ndouble doubleValue = reader.ReadDouble();\n
    "},{"location":"Streams/EndianReaders/BigEndianReader/#reading-from-offset","title":"Reading from Offset","text":"
    BigEndianReader reader = new BigEndianReader(GetPointer());\n\nbyte byteValue = reader.ReadByteAtOffset(5);\nuint uintValue = reader.ReadUIntAtOffset(10);\ndouble doubleValue = reader.ReadDoubleAtOffset(15);\n
    "},{"location":"Streams/EndianReaders/BigEndianReader/#advancing-the-pointer","title":"Advancing the Pointer","text":"
    BigEndianReader reader = new BigEndianReader(GetPointer(););\n\nreader.Seek(10); // Advances the pointer by 10 bytes.\n
    "},{"location":"Streams/EndianReaders/BigEndianWriter/","title":"BigEndianWriter","text":"

    Utility struct for writing to a pointer in Big Endian.

    BigEndianWriter is a struct providing methods for writing various types of data to a memory location, with the data being written in Big Endian byte order. This includes writing integers, floating point values, and arrays of bytes, either advancing the pointer after each write or writing at a specific offset without advancing the pointer.

    "},{"location":"Streams/EndianReaders/BigEndianWriter/#properties","title":"Properties","text":""},{"location":"Streams/EndianReaders/BigEndianWriter/#ptr","title":"Ptr","text":"
    public byte* Ptr;\n

    Current pointer being written to.

    "},{"location":"Streams/EndianReaders/BigEndianWriter/#constructors","title":"Constructors","text":""},{"location":"Streams/EndianReaders/BigEndianWriter/#bigendianwriter_1","title":"BigEndianWriter","text":"
    public BigEndianWriter(byte* ptr)\n

    Creates a simple wrapper around a pointer that writes in Big Endian. ptr is the pointer to the item behind the writer.

    "},{"location":"Streams/EndianReaders/BigEndianWriter/#methods","title":"Methods","text":""},{"location":"Streams/EndianReaders/BigEndianWriter/#write","title":"Write","text":"
    public void Write(sbyte value)\npublic void Write(byte value)\npublic void Write(short value)\npublic void Write(ushort value)\npublic void Write(int value)\npublic void Write(uint value)\npublic void Write(long value)\npublic void Write(ulong value)\npublic void Write(float value)\npublic void Write(double value)\npublic void Write(Span<byte> data)\n

    Writes a value to the current pointer and advances the pointer. Overloads exist for various data types including sbyte, byte, short, ushort, int, uint, long, ulong, float, double, and Span<byte>.

    "},{"location":"Streams/EndianReaders/BigEndianWriter/#writeatoffset","title":"WriteAtOffset","text":"
    public void WriteAtOffset(sbyte value, int offset)\npublic void WriteAtOffset(byte value, int offset)\npublic void WriteAtOffset(short value, int offset)\npublic void WriteAtOffset(ushort value, int offset)\npublic void WriteAtOffset(int value, int offset)\npublic void WriteAtOffset(uint value, int offset)\npublic void WriteAtOffset(long value, int offset)\npublic void WriteAtOffset(ulong value, int offset)\npublic void WriteAtOffset(float value, int offset)\npublic void WriteAtOffset(double value, int offset)\n

    Writes a value to the specified offset without advancing the pointer. Overloads exist for various data types including sbyte, byte, short, ushort, int, uint, long, ulong, float, double.

    "},{"location":"Streams/EndianReaders/BigEndianWriter/#seek","title":"Seek","text":"
    public void Seek(int offset)\n

    Advances the stream by a specified number of bytes. offset is the number of bytes to advance by.

    "},{"location":"Streams/EndianReaders/BigEndianWriter/#about-the-offset-methods","title":"About the Offset Methods","text":"

    The BigEndianWriter struct provides several methods that operate on a specific offset without advancing the pointer.

    While these methods do not significantly reduce the instruction count, they offer some minor performance advantages, you can read more about this in About Section

    "},{"location":"Streams/EndianReaders/BigEndianWriter/#usage","title":"Usage","text":"

    Example usage of the BigEndianWriter struct:

    var writer = new BigEndianWriter(ptr);\n\nwriter.Write((int)12345);  // Write an int\nwriter.Write((byte)65);    // Write a byte\nwriter.WriteAtOffset((long)9876543210, 5);  // Write a long at offset 5 from current pointer\n
    "},{"location":"Streams/EndianReaders/LittleEndianReader/","title":"LittleEndianReader","text":"

    A struct for reading from a pointer in Big Endian.

    LittleEndianReader is preferred over BufferedStreamReader when all data is already in memory.

    The LittleEndianReader struct provides utility methods for reading various data types from a pointer in Big Endian format.

    "},{"location":"Streams/EndianReaders/LittleEndianReader/#methods","title":"Methods","text":""},{"location":"Streams/EndianReaders/LittleEndianReader/#read-methods","title":"Read Methods","text":"

    These methods read the specified data type from the current pointer in Big Endian format and advance the pointer.

    public byte ReadByte()\npublic sbyte ReadSByte()\npublic short ReadShort()\npublic ushort ReadUShort()\npublic uint ReadUInt()\npublic int ReadInt()\npublic ulong ReadULong()\npublic long ReadLong()\npublic float ReadFloat()\npublic double ReadDouble()\n
    "},{"location":"Streams/EndianReaders/LittleEndianReader/#readatoffset-methods","title":"ReadAtOffset Methods","text":"

    These methods read the specified data type from the specified offset in Big Endian format without advancing the pointer.

    public byte ReadByteAtOffset(int offset)\npublic sbyte ReadSByteAtOffset(int offset)\npublic short ReadShortAtOffset(int offset)\npublic ushort ReadUShortAtOffset(int offset)\npublic uint ReadUIntAtOffset(int offset)\npublic int ReadIntAtOffset(int offset)\npublic ulong ReadULongAtOffset(int offset)\npublic long ReadLongAtOffset(int offset)\npublic float ReadFloatAtOffset(int offset)\npublic double ReadDoubleAtOffset(int offset)\n
    "},{"location":"Streams/EndianReaders/LittleEndianReader/#seek-method","title":"Seek Method","text":"

    This method advances the pointer by a specified number of bytes.

    public void Seek(int offset)\n
    "},{"location":"Streams/EndianReaders/LittleEndianReader/#about-the-offset-methods","title":"About the Offset Methods","text":"

    The LittleEndianReader struct provides several methods that read from a specific offset without advancing the pointer. These methods include ReadShortAtOffset, ReadIntAtOffset, ReadLongAtOffset, and ReadUlongAtOffset.

    While these methods do not significantly reduce the instruction count, they offer some minor performance advantages, you can read more about this in About Section

    "},{"location":"Streams/EndianReaders/LittleEndianReader/#usage","title":"Usage","text":""},{"location":"Streams/EndianReaders/LittleEndianReader/#reading-from-pointer","title":"Reading from Pointer","text":"
    LittleEndianReader reader = new LittleEndianReader(GetPointer());\n\nbyte byteValue = reader.ReadByte();\nuint uintValue = reader.ReadUInt();\ndouble doubleValue = reader.ReadDouble();\n
    "},{"location":"Streams/EndianReaders/LittleEndianReader/#reading-from-offset","title":"Reading from Offset","text":"
    LittleEndianReader reader = new LittleEndianReader(GetPointer());\n\nbyte byteValue = reader.ReadByteAtOffset(5);\nuint uintValue = reader.ReadUIntAtOffset(10);\ndouble doubleValue = reader.ReadDoubleAtOffset(15);\n
    "},{"location":"Streams/EndianReaders/LittleEndianReader/#advancing-the-pointer","title":"Advancing the Pointer","text":"
    LittleEndianReader reader = new LittleEndianReader(GetPointer(););\n\nreader.Seek(10); // Advances the pointer by 10 bytes.\n
    "},{"location":"Streams/EndianReaders/LittleEndianWriter/","title":"LittleEndianWriter","text":"

    Utility struct for writing to a pointer in Big Endian.

    LittleEndianWriter is a struct providing methods for writing various types of data to a memory location, with the data being written in Big Endian byte order. This includes writing integers, floating point values, and arrays of bytes, either advancing the pointer after each write or writing at a specific offset without advancing the pointer.

    "},{"location":"Streams/EndianReaders/LittleEndianWriter/#properties","title":"Properties","text":""},{"location":"Streams/EndianReaders/LittleEndianWriter/#ptr","title":"Ptr","text":"
    public byte* Ptr;\n

    Current pointer being written to.

    "},{"location":"Streams/EndianReaders/LittleEndianWriter/#constructors","title":"Constructors","text":""},{"location":"Streams/EndianReaders/LittleEndianWriter/#littleendianwriter_1","title":"LittleEndianWriter","text":"
    public LittleEndianWriter(byte* ptr)\n

    Creates a simple wrapper around a pointer that writes in Big Endian. ptr is the pointer to the item behind the writer.

    "},{"location":"Streams/EndianReaders/LittleEndianWriter/#methods","title":"Methods","text":""},{"location":"Streams/EndianReaders/LittleEndianWriter/#write","title":"Write","text":"
    public void Write(sbyte value)\npublic void Write(byte value)\npublic void Write(short value)\npublic void Write(ushort value)\npublic void Write(int value)\npublic void Write(uint value)\npublic void Write(long value)\npublic void Write(ulong value)\npublic void Write(float value)\npublic void Write(double value)\npublic void Write(Span<byte> data)\n

    Writes a value to the current pointer and advances the pointer. Overloads exist for various data types including sbyte, byte, short, ushort, int, uint, long, ulong, float, double, and Span<byte>.

    "},{"location":"Streams/EndianReaders/LittleEndianWriter/#writeatoffset","title":"WriteAtOffset","text":"
    public void WriteAtOffset(sbyte value, int offset)\npublic void WriteAtOffset(byte value, int offset)\npublic void WriteAtOffset(short value, int offset)\npublic void WriteAtOffset(ushort value, int offset)\npublic void WriteAtOffset(int value, int offset)\npublic void WriteAtOffset(uint value, int offset)\npublic void WriteAtOffset(long value, int offset)\npublic void WriteAtOffset(ulong value, int offset)\npublic void WriteAtOffset(float value, int offset)\npublic void WriteAtOffset(double value, int offset)\n

    Writes a value to the specified offset without advancing the pointer. Overloads exist for various data types including sbyte, byte, short, ushort, int, uint, long, ulong, float, double.

    "},{"location":"Streams/EndianReaders/LittleEndianWriter/#seek","title":"Seek","text":"
    public void Seek(int offset)\n

    Advances the stream by a specified number of bytes. offset is the number of bytes to advance by.

    "},{"location":"Streams/EndianReaders/LittleEndianWriter/#about-the-offset-methods","title":"About the Offset Methods","text":"

    The LittleEndianWriter struct provides several methods that operate on a specific offset without advancing the pointer.

    While these methods do not significantly reduce the instruction count, they offer some minor performance advantages, you can read more about this in About Section

    "},{"location":"Streams/EndianReaders/LittleEndianWriter/#usage","title":"Usage","text":"

    Example usage of the LittleEndianWriter struct:

    var writer = new LittleEndianWriter(ptr);\n\nwriter.Write((int)12345);  // Write an int\nwriter.Write((byte)65);    // Write a byte\nwriter.WriteAtOffset((long)9876543210, 5);  // Write a long at offset 5 from current pointer\n
    "},{"location":"Utilities/ArrayRental/","title":"ArrayRental","text":"

    ArrayRental is a struct that represents an instance of a rented array. It should be disposed of after use with the using statement.

    If you need a generic version, use ArrayRental<T>.

    The underlying array is managed by the shared ArrayPool.

    "},{"location":"Utilities/ArrayRental/#properties","title":"Properties","text":"
    • Array: The underlying array for this rental.
    • Span: Span for the underlying array. May be larger than requested length.
    "},{"location":"Utilities/ArrayRental/#constructor","title":"Constructor","text":"
    public ArrayRental(int numBytes)\n

    Rents a requested minimum number of bytes. Amount of data rented might be larger.

    "},{"location":"Utilities/ArrayRental/#slices","title":"Slices","text":"

    ArrayRentalSlice represents a slice of an ArrayRental. This API is meant to be used as a return value from methods, and transfers ownership of the rental from the internal ArrayRental.

    public ArrayRentalSlice(ArrayRental rental, int length)\n

    Represents a slice of the array rental.

    "},{"location":"Utilities/ArrayRental/#usage","title":"Usage","text":""},{"location":"Utilities/ArrayRental/#rent-an-array-and-create-a-slice","title":"Rent an Array and Create a Slice","text":"

    Make sure to dispose with using statement or explicit dispose.

    // Will create a rental of at least 4096 bytes.\nusing var rental = new ArrayRental(4096);\n
    "},{"location":"Utilities/ArrayRental/#rent-an-array-and-create-a-slice_1","title":"Rent an Array and Create a Slice","text":"

    When you create an ArrayRentalSlice, the responsibility of disposing the rental is transferred to the slice. Make sure to not double dispose.

    // Some Method\nArrayRentalSlice CompressData(byte* data, int length) {\nvar rental = new ArrayRental(numBytes);\n// Compress into rental....\n// And return a slice with just the info needed.\nreturn new ArrayRentalSlice(rental, sliceLength);\n}\n\n// Method consumer\nusing var compressed = CompressData(data, length);\n
    "},{"location":"Utilities/Box/","title":"Box

    Forked from Community Toolkit.

    A class representing a boxed value type, providing build-time validation and automatic unboxing.

    Box is a utility class that represents a boxed value type on the managed heap. It can be used in place of a non-generic object reference to a boxed value type, making the code more expressive and reducing the chances of errors.","text":""},{"location":"Utilities/Box/#methods","title":"Methods","text":""},{"location":"Utilities/Box/#getfrom","title":"GetFrom","text":"

    public static Box<T> GetFrom(object obj)\n

    Returns a Box<T> reference from the input object instance, representing a boxed T value.

    "},{"location":"Utilities/Box/#dangerousgetfrom","title":"DangerousGetFrom","text":"
    public static Box<T> DangerousGetFrom(object obj)\n

    Returns a Box<T> reference from the input object instance, representing a boxed T value. This method doesn't check the actual type of obj, so it is the responsibility of the caller to ensure it actually represents a boxed T value and not some other instance.

    "},{"location":"Utilities/Box/#trygetfrom","title":"TryGetFrom","text":"
    public static bool TryGetFrom(object obj, out Box<T>? box)\n

    Tries to get a Box<T> reference from an input object representing a boxed T value. Returns true if a Box<T> instance was retrieved correctly, false otherwise.

    "},{"location":"Utilities/Box/#operators","title":"Operators","text":""},{"location":"Utilities/Box/#implicit-operator-t","title":"implicit operator T","text":"
    public static implicit operator T(Box<T> box)\n

    Implicitly gets the T value from a given Box<T> instance.

    "},{"location":"Utilities/Box/#implicit-operator-box","title":"implicit operator Box
    public static implicit operator Box<T>(T value)\n

    Implicitly creates a new Box<T> instance from a given T value.

    ","text":""},{"location":"Utilities/Box/#usage","title":"Usage","text":""},{"location":"Utilities/Box/#box-and-unbox-value-type-with-build-time-validation","title":"Box and Unbox Value Type with Build-time Validation
    Box<int> box = 42;\nint sum = box.Value + 1;\n
    ","text":""},{"location":"Utilities/Box/#retrieve-a-mutable-reference-to-a-boxed-value","title":"Retrieve a Mutable Reference to a Boxed Value
    Box<MyStruct> box = new MyStruct { Field1 = 1, Field2 = 2 };\nref MyStruct myStructRef = ref box.GetReference();\nmyStructRef.Field1 = 3;\n
    ","text":""},{"location":"Utilities/Box/#extension-methods","title":"Extension Methods","text":""},{"location":"Utilities/Box/#getreference","title":"GetReference
    public static ref T GetReference<T>(this Box<T> box) where T : struct\n

    Gets a T reference from a Box<T> instance.

    ","text":""},{"location":"Utilities/Box/#usage_1","title":"Usage
    Box<MyStruct> box = new MyStruct { Field1 = 1, Field2 = 2 };\nref MyStruct myStructRef = ref box.GetReference();\n
    ","text":""},{"location":"Utilities/CircularBuffer/","title":"CircularBuffer Class","text":"

    The CircularBuffer is a writable buffer useful for temporary storage of data. It's a buffer whereby once you reach the end of the buffer, it loops back over to the beginning of the buffer, overwriting old elements.

    "},{"location":"Utilities/CircularBuffer/#properties","title":"Properties","text":"
    • Start: The address of the CircularBuffer.
    • End: The address of the CircularBuffer.
    • Current: Address of the current item in the buffer.
    • Remaining: Remaining space in the buffer.
    • Size: The overall size of the buffer.
    "},{"location":"Utilities/CircularBuffer/#constructors","title":"Constructors","text":"
    • CircularBuffer(nuint start, int size): Creates a CircularBuffer within the target memory source.
    "},{"location":"Utilities/CircularBuffer/#methods","title":"Methods","text":""},{"location":"Utilities/CircularBuffer/#add","title":"Add","text":"
    public nuint Add(byte* data, uint length)\npublic nuint Add<TSource>(TSource source, byte* data, uint length)\npublic nuint Add<TSource, T>(TSource source, T value)\npublic nuint Add<T>(T value)\n

    Adds a new item onto the circular buffer. Returns a pointer to the recently added item to the buffer, or zero if the item cannot fit.

    "},{"location":"Utilities/CircularBuffer/#canitemfit","title":"CanItemFit","text":"
    public ItemFit CanItemFit(uint itemSize)\npublic ItemFit CanItemFit<T>()\n

    Returns an enumerable describing if an item can fit into the buffer.

    "},{"location":"Utilities/CircularBuffer/#itemfit-enum","title":"ItemFit Enum","text":"

    Describes whether an item can fit into a given buffer.

    • Yes: The item can fit into the buffer.
    • StartOfBuffer: The item can fit into the buffer, but not in the remaining space (will be placed at start of buffer).
    • No: The item is too large to fit into the buffer.
    "},{"location":"Utilities/CircularBuffer/#examples","title":"Examples","text":""},{"location":"Utilities/CircularBuffer/#adding-an-integer-to-the-buffer","title":"Adding an Integer to The Buffer","text":"
    var circularBuffer = new CircularBuffer((nuint)bufferStartPtr, bufferSize);\nnuint pointerToValue = circularBuffer.Add(42);\n\nif (pointerToValue != UIntPtr.Zero)\nConsole.WriteLine(\"Value added successfully!\");\nelse\nConsole.WriteLine(\"Failed to add value to the buffer.\");\n
    "},{"location":"Utilities/CircularBuffer/#adding-a-custom-struct-to-the-buffer","title":"Adding a Custom Struct to The Buffer","text":"
    var circularBuffer = new CircularBuffer((nuint)bufferStart, bufferSize);\nvar valueToAdd = new Vector2 { X = 1, Y = 2 };\nnuint pointerToValue = circularBuffer.Add(valueToAdd);\n\nif (pointerToValue != UIntPtr.Zero)\nConsole.WriteLine(\"Value added successfully!\");\nelse\nConsole.WriteLine(\"Failed to add value to the buffer.\");\n
    "},{"location":"Utilities/CircularBuffer/#checking-if-an-item-can-fit-in-the-buffer","title":"Checking if an item can fit in the buffer.","text":"
    var circularBuffer = new CircularBuffer((nuint)bufferStart, bufferSize);\nvar result = circularBuffer.CanItemFit<double>();\n\nswitch (result)\n{\ncase CircularBuffer.ItemFit.Yes:\n// \"A double can fit in the buffer.\"\nbreak;\ncase CircularBuffer.ItemFit.StartOfBuffer:\n// \"A double can fit in the buffer, but it will be placed at the start of the buffer.\"\nbreak;\ncase CircularBuffer.ItemFit.No:\n// \"A double cannot fit in the buffer.\"\nbreak;\n}\n
    "},{"location":"Utilities/Endian/","title":"Endian Class","text":"

    The Endian class provides various utilities for converting primitives and structures between endians.

    "},{"location":"Utilities/Endian/#methods","title":"Methods","text":""},{"location":"Utilities/Endian/#reverse","title":"Reverse","text":"
    public static byte Reverse(byte value)\npublic static sbyte Reverse(sbyte value)\npublic static short Reverse(short value)\npublic static ushort Reverse(ushort value)\npublic static int Reverse(int value)\npublic static uint Reverse(uint value)\npublic static long Reverse(long value)\npublic static ulong Reverse(ulong value)\npublic static float Reverse(float value)\npublic static double Reverse(double value)\n

    Reverses the byte order of the specified value.

    "},{"location":"Utilities/Endian/#reverse-generic","title":"Reverse (Generic)","text":"

    Info

    Utility method for structs with single values.

    Warning

    This method is provided for convenience. If the item size is not 1/2/4/8 bytes, this method will throw.

    public static T Reverse<T>(T value) where T : unmanaged\n

    Reverses the endian of a primitive value such as int, short, float, double etc.

    "},{"location":"Utilities/Endian/#examples","title":"Examples","text":""},{"location":"Utilities/Endian/#reversing-an-integers-endian","title":"Reversing an Integer's Endian","text":"
    int value = 42;\nint reversedValue = Endian.Reverse(value);\n\nConsole.WriteLine($\"Original Value: {value}, Reversed Value: {reversedValue}\");\n

    This will print something like:

    Original Value: 42, Reversed Value: 704643072\n
    "},{"location":"Utilities/Endian/#reversing-a-custom-structs-endian","title":"Reversing a Custom Struct's Endian","text":"

    Warning

    This will only work if the struct is a blittable type.

    struct NamedOffset\n{\npublic int Offset;\n}\n\nMyStruct value = new NamedOffset { Offset = 1 };\nMyStruct reversedValue = Endian.Reverse(value);\n\nConsole.WriteLine($\"Original Value: {value.X}, Reversed Value: {reversedValue.X}\");\n

    This will print something like:

    Original Value: 1 Reversed Value: 16777216\n
    "},{"location":"Utilities/ObjectMarshal/","title":"ObjectMarshal","text":"

    Forked from Community Toolkit.

    Utility class providing methods for working with object instances.

    ObjectMarshal is a utility class that provides methods for calculating byte offsets to specific fields within objects, retrieving references to data within objects at specific offsets, and unboxing values from objects.

    "},{"location":"Utilities/ObjectMarshal/#methods","title":"Methods","text":""},{"location":"Utilities/ObjectMarshal/#dangerousgetobjectdatabyteoffset","title":"DangerousGetObjectDataByteOffset","text":"
    public static IntPtr DangerousGetObjectDataByteOffset<T>(object obj, ref T data)\n

    Calculates the byte offset to a specific field within a given object. The input parameters are not validated, and it's the responsibility of the caller to ensure that the data reference is actually pointing to a memory location within obj.

    "},{"location":"Utilities/ObjectMarshal/#dangerousgetobjectdatareferenceat","title":"DangerousGetObjectDataReferenceAt","text":"
    public static ref T DangerousGetObjectDataReferenceAt<T>(object obj, IntPtr offset)\n

    Gets a T reference to data within a given object at a specified offset. None of the input arguments is validated, and it is the responsibility of the caller to ensure they are valid.

    "},{"location":"Utilities/ObjectMarshal/#tryunbox","title":"TryUnbox","text":"
    public static bool TryUnbox<T>(this object obj, out T value) where T : struct\n

    Tries to get a boxed T value from an input object instance. Returns true if a T value was retrieved correctly, false otherwise.

    "},{"location":"Utilities/ObjectMarshal/#dangerousunbox","title":"DangerousUnbox","text":"
    public static ref T DangerousUnbox<T>(object obj) where T : struct\n

    Unboxes a T value from an input object instance. Throws an InvalidCastException when obj is not of type T.

    "},{"location":"Utilities/ObjectMarshal/#usage","title":"Usage","text":""},{"location":"Utilities/ObjectMarshal/#calculate-byte-offset","title":"Calculate Byte Offset","text":"
    MyStruct myStruct = new MyStruct();\nref int fieldRef = ref myStruct.SomeIntField;\nIntPtr offset = ObjectMarshal.DangerousGetObjectDataByteOffset(myStruct, ref fieldRef);\n
    "},{"location":"Utilities/ObjectMarshal/#get-reference-at-specific-offset","title":"Get Reference At Specific Offset","text":"
    MyStruct myStruct = new MyStruct();\nIntPtr fieldOffset = /* calculated offset */;\nref int fieldRef = ref ObjectMarshal.DangerousGetObjectDataReferenceAt<MyStruct>(myStruct, fieldOffset);\n
    "},{"location":"Utilities/ObjectMarshal/#try-to-unbox-a-value","title":"Try to Unbox a value","text":"
    object boxedInt = 42;\nint unboxedInt;\n\nif (boxedInt.TryUnbox(out unboxedInt))\nConsole.WriteLine($\"Unboxed value: {unboxedInt}\");\n
    "},{"location":"Utilities/ObjectMarshal/#unbox-a-value","title":"Unbox a value","text":"
    object boxedInt = 42;\nref int unboxedInt = ref ObjectMarshal.DangerousUnbox<int>(boxedInt);\n
    "},{"location":"Utilities/Pinnable/","title":"Pinnable<T>","text":"

    Allows you to pin an unmanaged object in a static location in memory, to be later accessible from native code.

    Assume value is copied; modify the Pinnable instance to read/write values once created.

    The Pinnable<T> class provides a way to pin native unmanaged objects in memory, ensuring that their memory addresses remain constant during the lifetime of the Pinnable<T> instance. This can be useful when working with native code that requires static memory addresses.

    On newer runtimes, the memory is allocated into the Pinned Object Heap (POH); thus has no impact on effectiveness of regular garbage collection.

    "},{"location":"Utilities/Pinnable/#properties","title":"Properties","text":"
    • Value: The value pointed to by the Pointer. If the class was instantiated using an array, this is the first element of the array.
    • Pointer: Pointer to the native value in question. If the class was instantiated using an array, this is the pointer to the first element of the array.
    "},{"location":"Utilities/Pinnable/#constructors","title":"Constructors","text":"
    public Pinnable(T[] value);   // Pins an array of values to the heap.\npublic Pinnable(in T value);     // Pins a single value to the heap.\n
    "},{"location":"Utilities/Pinnable/#disposal","title":"Disposal","text":"

    The Pinnable<T> class implements the IDisposable interface, which means you should dispose of the instance when you are done with it.

    This can be done using the using statement, or by explicitly calling the Dispose() method.

    "},{"location":"Utilities/Pinnable/#examples","title":"Examples","text":""},{"location":"Utilities/Pinnable/#pinning-a-single-value","title":"Pinning a Single Value","text":"
    int value = 42;\n\nusing var pinnable = new Pinnable<int>(value);\n// Access the pinned value through pinnable.Value\n// Access the memory address of the pinned value through pinnable.Pointer\n
    "},{"location":"Utilities/Pinnable/#pinning-an-array","title":"Pinning an Array","text":"
    int[] array = new int[] { 1, 2, 3, 4, 5 };\n\nusing var pinnable = new Pinnable<int>(value);\n// Access array element via `pinnable[x]`.\n// Access the first element of the pinned array through pinnable.Value\n// Access the memory address of the first element of the pinned array through pinnable.Pointer\n
    "},{"location":"Utilities/TypeInfo/","title":"TypeInfo","text":"

    Utility class providing methods for obtaining information about different types.

    "},{"location":"Utilities/TypeInfo/#methods","title":"Methods","text":""},{"location":"Utilities/TypeInfo/#approximateisblittable","title":"ApproximateIsBlittable","text":"

    public static bool ApproximateIsBlittable<T>()\n
    Returns true if a type is blittable, else false. This method uses an approximation, and may not work with generic types with blittable (unmanaged) constraints.

    "},{"location":"Utilities/TypeInfo/#approximateisblittable_1","title":"ApproximateIsBlittable","text":"

    public static bool ApproximateIsBlittable(Type type)\n
    Returns true if a type is blittable, else false. This method uses an approximation, and may not work with generic types with blittable (unmanaged) constraints.

    "},{"location":"Utilities/TypeInfo/#marshalledsizeof","title":"MarshalledSizeOf","text":"

    public static int MarshalledSizeOf<T>()\n
    Returns size of item after marshalling is performed. This caches the value, thus is faster to access.

    "},{"location":"Utilities/TypeInfo/#usage","title":"Usage","text":""},{"location":"Utilities/TypeInfo/#check-if-a-type-is-blittable-generic","title":"Check if a Type is Blittable (Generic)","text":"
    bool isBlittable = TypeInfo.ApproximateIsBlittable<int>();\n
    "},{"location":"Utilities/TypeInfo/#check-if-a-type-is-blittable-non-generic","title":"Check if a Type is Blittable (Non-Generic)","text":"
    bool isBlittable = TypeInfo.ApproximateIsBlittable(typeof(int));\n
    "},{"location":"Utilities/TypeInfo/#check-size-of-type-after-marshalling","title":"Check size of Type After Marshalling","text":"
    int size = TypeInfo.MarshalledSizeOf<int>();\n
    "}]} \ No newline at end of file diff --git a/sitemap.xml b/sitemap.xml new file mode 100644 index 0000000..f5fd22b --- /dev/null +++ b/sitemap.xml @@ -0,0 +1,173 @@ + + + + https://github.com/Reloaded-Project/Reloaded.Memory/ + 2024-02-21 + daily + + + https://github.com/Reloaded-Project/Reloaded.Memory/About-Memory/ + 2024-02-21 + daily + + + https://github.com/Reloaded-Project/Reloaded.Memory/Extensions/ArrayExtensions/ + 2024-02-21 + daily + + + https://github.com/Reloaded-Project/Reloaded.Memory/Extensions/BoolExtensions/ + 2024-02-21 + daily + + + https://github.com/Reloaded-Project/Reloaded.Memory/Extensions/EndianExtensions/ + 2024-02-21 + daily + + + https://github.com/Reloaded-Project/Reloaded.Memory/Extensions/EnumExtensions/ + 2024-02-21 + daily + + + https://github.com/Reloaded-Project/Reloaded.Memory/Extensions/SpanExtensions/ + 2024-02-21 + daily + + + https://github.com/Reloaded-Project/Reloaded.Memory/Extensions/StreamExtensions/ + 2024-02-21 + daily + + + https://github.com/Reloaded-Project/Reloaded.Memory/Extensions/StringExtensions/ + 2024-02-21 + daily + + + https://github.com/Reloaded-Project/Reloaded.Memory/Extensions/VectorExtensions/ + 2024-02-21 + daily + + + https://github.com/Reloaded-Project/Reloaded.Memory/Pointers/FixedArrayPtr/ + 2024-02-21 + daily + + + https://github.com/Reloaded-Project/Reloaded.Memory/Pointers/Ptr/ + 2024-02-21 + daily + + + https://github.com/Reloaded-Project/Reloaded.Memory/Reloaded/Readme/ + 2024-02-21 + daily + + + https://github.com/Reloaded-Project/Reloaded.Memory/Reloaded/Pages/ + 2024-02-21 + daily + + + https://github.com/Reloaded-Project/Reloaded.Memory/Reloaded/Pages/contributing/ + 2024-02-21 + daily + + + https://github.com/Reloaded-Project/Reloaded.Memory/Reloaded/Pages/license/ + 2024-02-21 + daily + + + https://github.com/Reloaded-Project/Reloaded.Memory/Reloaded/Pages/testing-zone/ + 2024-02-21 + daily + + + https://github.com/Reloaded-Project/Reloaded.Memory/Reloaded/docs/Pages/ + 2024-02-21 + daily + + + https://github.com/Reloaded-Project/Reloaded.Memory/Reloaded/docs/Pages/contributing/ + 2024-02-21 + daily + + + https://github.com/Reloaded-Project/Reloaded.Memory/Reloaded/docs/Pages/license/ + 2024-02-21 + daily + + + https://github.com/Reloaded-Project/Reloaded.Memory/Reloaded/docs/Pages/testing-zone/ + 2024-02-21 + daily + + + https://github.com/Reloaded-Project/Reloaded.Memory/Streams/BufferedStreamReader/ + 2024-02-21 + daily + + + https://github.com/Reloaded-Project/Reloaded.Memory/Streams/EndianReaders/About/ + 2024-02-21 + daily + + + https://github.com/Reloaded-Project/Reloaded.Memory/Streams/EndianReaders/BigEndianReader/ + 2024-02-21 + daily + + + https://github.com/Reloaded-Project/Reloaded.Memory/Streams/EndianReaders/BigEndianWriter/ + 2024-02-21 + daily + + + https://github.com/Reloaded-Project/Reloaded.Memory/Streams/EndianReaders/LittleEndianReader/ + 2024-02-21 + daily + + + https://github.com/Reloaded-Project/Reloaded.Memory/Streams/EndianReaders/LittleEndianWriter/ + 2024-02-21 + daily + + + https://github.com/Reloaded-Project/Reloaded.Memory/Utilities/ArrayRental/ + 2024-02-21 + daily + + + https://github.com/Reloaded-Project/Reloaded.Memory/Utilities/Box/ + 2024-02-21 + daily + + + https://github.com/Reloaded-Project/Reloaded.Memory/Utilities/CircularBuffer/ + 2024-02-21 + daily + + + https://github.com/Reloaded-Project/Reloaded.Memory/Utilities/Endian/ + 2024-02-21 + daily + + + https://github.com/Reloaded-Project/Reloaded.Memory/Utilities/ObjectMarshal/ + 2024-02-21 + daily + + + https://github.com/Reloaded-Project/Reloaded.Memory/Utilities/Pinnable/ + 2024-02-21 + daily + + + https://github.com/Reloaded-Project/Reloaded.Memory/Utilities/TypeInfo/ + 2024-02-21 + daily + + \ No newline at end of file diff --git a/sitemap.xml.gz b/sitemap.xml.gz new file mode 100644 index 0000000..a16ecd8 Binary files /dev/null and b/sitemap.xml.gz differ