forked from EPD-Libraries/BymlLibrary
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
e96b288
commit 09c184b
Showing
9 changed files
with
311 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
using BymlLibrary.Extensions; | ||
using BymlLibrary.Writers; | ||
using BymlLibrary.Yaml; | ||
using System.Diagnostics.CodeAnalysis; | ||
using System.Runtime.CompilerServices; | ||
using VYaml.Emitter; | ||
|
||
namespace BymlLibrary.Nodes.Containers; | ||
|
||
public class BymlArrayChangelog : SortedDictionary<int, Byml>, IBymlNode | ||
{ | ||
public BymlArrayChangelog() | ||
{ | ||
} | ||
|
||
public BymlArrayChangelog(IDictionary<int, Byml> values) : base(values) | ||
{ | ||
} | ||
|
||
public void EmitYaml(ref Utf8YamlEmitter emitter) | ||
{ | ||
emitter.Tag("!array_changelog"); | ||
emitter.BeginMapping((Count < Byml.YamlConfig.InlineContainerMaxCount && !HasContainerNodes()) switch { | ||
true => MappingStyle.Flow, | ||
false => MappingStyle.Block, | ||
}); | ||
|
||
foreach (var (hash, node) in this) { | ||
emitter.WriteInt32(hash); | ||
BymlYamlWriter.Write(ref emitter, node); | ||
} | ||
|
||
emitter.EndMapping(); | ||
} | ||
|
||
public bool HasContainerNodes() | ||
{ | ||
foreach (var (_, node) in this) { | ||
if (node.Type.IsContainerType()) { | ||
return true; | ||
} | ||
} | ||
|
||
return false; | ||
} | ||
|
||
public int GetValueHash() | ||
{ | ||
HashCode hashCode = new(); | ||
foreach (var (key, node) in this) { | ||
hashCode.Add(key); | ||
hashCode.Add(Byml.ValueEqualityComparer.Default.GetHashCode(node)); | ||
} | ||
|
||
return hashCode.ToHashCode(); | ||
} | ||
|
||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
int IBymlNode.Collect(in BymlWriter writer) | ||
{ | ||
HashCode hashCode = new(); | ||
foreach (var (key, node) in this) { | ||
hashCode.Add(key); | ||
hashCode.Add(writer.Collect(node)); | ||
} | ||
|
||
return hashCode.ToHashCode(); | ||
} | ||
|
||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
void IBymlNode.Write(BymlWriter context, Action<Byml> write) | ||
{ | ||
context.WriteContainerHeader(BymlNodeType.ArrayChangelog, Count); | ||
foreach (var (key, node) in this) { | ||
context.Writer.Write(key); | ||
write(node); | ||
} | ||
|
||
foreach (Byml node in Values) { | ||
context.Writer.Write(node.Type); | ||
} | ||
|
||
context.Writer.Align(4); | ||
} | ||
|
||
public class ValueEqualityComparer : IEqualityComparer<BymlArrayChangelog> | ||
{ | ||
public bool Equals(BymlArrayChangelog? x, BymlArrayChangelog? y) | ||
{ | ||
if (x is null || y is null) { | ||
return y == x; | ||
} | ||
|
||
if (x.Count != y.Count) { | ||
return false; | ||
} | ||
|
||
return x.Keys.SequenceEqual(y.Keys) && x.Values.SequenceEqual(y.Values, Byml.ValueEqualityComparer.Default); | ||
} | ||
|
||
public int GetHashCode([DisallowNull] BymlArrayChangelog obj) | ||
{ | ||
throw new NotImplementedException(); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
145 changes: 145 additions & 0 deletions
145
src/BymlLibrary/Nodes/Immutable/Containers/ImmutableBymlArrayChangelog.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
using BymlLibrary.Extensions; | ||
using BymlLibrary.Nodes.Containers; | ||
using BymlLibrary.Structures; | ||
using BymlLibrary.Yaml; | ||
using Revrs; | ||
using Revrs.Extensions; | ||
using System.Runtime.CompilerServices; | ||
using System.Runtime.InteropServices; | ||
using VYaml.Emitter; | ||
|
||
namespace BymlLibrary.Nodes.Immutable.Containers; | ||
|
||
public readonly ref struct ImmutableBymlArrayChangelog(Span<byte> data, int offset, int count) | ||
{ | ||
/// <summary> | ||
/// Span of the BYMl data | ||
/// </summary> | ||
private readonly Span<byte> _data = data; | ||
|
||
/// <summary> | ||
/// The container item count | ||
/// </summary> | ||
public readonly int Count = count; | ||
|
||
/// <summary> | ||
/// Container offset entries | ||
/// </summary> | ||
private readonly Span<Entry> _entries = count == 0 ? [] | ||
: data[(offset + BymlContainer.SIZE)..] | ||
.ReadSpan<Entry>(count); | ||
|
||
/// <summary> | ||
/// Container entry types | ||
/// </summary> | ||
private readonly Span<BymlNodeType> _types = count == 0 ? [] | ||
: data[(offset + BymlContainer.SIZE + (Entry.SIZE * count))..] | ||
.ReadSpan<BymlNodeType>(count); | ||
|
||
public readonly ImmutableBymlArrayChangelogEntry this[int index] { | ||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
get { | ||
Entry entry = _entries[index]; | ||
return new(entry.Index, _data, entry.Value, _types[index]); | ||
} | ||
} | ||
|
||
[StructLayout(LayoutKind.Sequential, Pack = 4, Size = SIZE)] | ||
private readonly struct Entry | ||
{ | ||
public const int SIZE = 8; | ||
|
||
public readonly int Index; | ||
public readonly int Value; | ||
|
||
public class Reverser : IStructReverser | ||
{ | ||
public static void Reverse(in Span<byte> slice) | ||
{ | ||
slice[0..4].Reverse(); | ||
slice[4..8].Reverse(); | ||
} | ||
} | ||
} | ||
|
||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
public readonly Enumerator GetEnumerator() | ||
=> new(this); | ||
|
||
[method: MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
public ref struct Enumerator(ImmutableBymlArrayChangelog container) | ||
{ | ||
private readonly ImmutableBymlArrayChangelog _container = container; | ||
private int _index = -1; | ||
|
||
public readonly ImmutableBymlArrayChangelogEntry Current { | ||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
get => _container[_index]; | ||
} | ||
|
||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
public bool MoveNext() | ||
{ | ||
if (++_index >= _container.Count) { | ||
return false; | ||
} | ||
|
||
return true; | ||
} | ||
} | ||
|
||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
public BymlArrayChangelog ToMutable(in ImmutableByml root) | ||
{ | ||
BymlArrayChangelog arrayChangelog = []; | ||
foreach (var (key, value) in this) { | ||
arrayChangelog[key] = Byml.FromImmutable(value, root); | ||
} | ||
|
||
return arrayChangelog; | ||
} | ||
|
||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
internal unsafe void EmitYaml(ref Utf8YamlEmitter emitter, in ImmutableByml root) | ||
{ | ||
emitter.Tag("!array-changelog"); | ||
emitter.BeginMapping((Count < Byml.YamlConfig.InlineContainerMaxCount && !HasContainerNodes()) switch { | ||
true => MappingStyle.Flow, | ||
false => MappingStyle.Block, | ||
}); | ||
|
||
foreach (var (index, node) in this) { | ||
emitter.WriteInt32(index); | ||
BymlYamlWriter.Write(ref emitter, node, root); | ||
} | ||
|
||
emitter.EndMapping(); | ||
} | ||
|
||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
private bool HasContainerNodes() | ||
{ | ||
foreach (var (_, node) in this) { | ||
if (node.Type.IsContainerType()) { | ||
return true; | ||
} | ||
} | ||
|
||
return false; | ||
} | ||
|
||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
public static void Reverse(ref RevrsReader reader, int offset, int count, in HashSet<int> reversedOffsets) | ||
{ | ||
for (int i = 0; i < count; i++) { | ||
Entry entry = reader.Read<Entry, Entry.Reverser>( | ||
offset + BymlContainer.SIZE + (Entry.SIZE * i) | ||
); | ||
|
||
ImmutableByml.ReverseNode(ref reader, entry.Value, | ||
reader.Read<BymlNodeType>(offset + BymlContainer.SIZE + (Entry.SIZE * count) + i), | ||
reversedOffsets | ||
); | ||
} | ||
} | ||
} |
13 changes: 13 additions & 0 deletions
13
src/BymlLibrary/Nodes/Immutable/Containers/ImmutableBymlArrayChangelogEntry.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
namespace BymlLibrary.Nodes.Immutable.Containers; | ||
|
||
public readonly ref struct ImmutableBymlArrayChangelogEntry(int index, Span<byte> data, int value, BymlNodeType type) | ||
{ | ||
public readonly int Index = index; | ||
public readonly ImmutableByml Node = new(data, value, type); | ||
|
||
public void Deconstruct(out int index, out ImmutableByml node) | ||
{ | ||
index = Index; | ||
node = Node; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters