-
Notifications
You must be signed in to change notification settings - Fork 125
/
SerializedStringsStream.cs
108 lines (90 loc) · 3.51 KB
/
SerializedStringsStream.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
using System.Collections.Generic;
using System.Text;
using AsmResolver.IO;
namespace AsmResolver.PE.DotNet.Metadata.Strings
{
/// <summary>
/// Provides an implementation of a strings stream that obtains strings from a readable segment in a file.
/// </summary>
public class SerializedStringsStream : StringsStream
{
private readonly Dictionary<uint, Utf8String> _cachedStrings = new();
private readonly BinaryStreamReader _reader;
/// <summary>
/// Creates a new strings stream with the provided byte array as the raw contents of the stream.
/// </summary>
/// <param name="rawData">The raw contents of the stream.</param>
public SerializedStringsStream(byte[] rawData)
: this(DefaultName, new BinaryStreamReader(rawData))
{
}
/// <summary>
/// Creates a new strings stream with the provided byte array as the raw contents of the stream.
/// </summary>
/// <param name="name">The name of the stream.</param>
/// <param name="rawData">The raw contents of the stream.</param>
public SerializedStringsStream(string name, byte[] rawData)
: this(name, new BinaryStreamReader(rawData))
{
}
/// <summary>
/// Creates a new strings stream with the provided file segment reader as the raw contents of the stream.
/// </summary>
/// <param name="name">The name of the stream.</param>
/// <param name="reader">The raw contents of the stream.</param>
public SerializedStringsStream(string name, in BinaryStreamReader reader)
: base(name)
{
_reader = reader;
Offset = reader.Offset;
Rva = reader.Rva;
}
/// <inheritdoc />
public override bool CanRead => true;
/// <inheritdoc />
public override BinaryStreamReader CreateReader() => _reader.Fork();
/// <inheritdoc />
public override uint GetPhysicalSize() => _reader.Length;
/// <inheritdoc />
public override void Write(IBinaryStreamWriter writer) => _reader.Fork().WriteToOutput(writer);
/// <inheritdoc />
public override Utf8String? GetStringByIndex(uint index)
{
if (index == 0)
return null;
if (!_cachedStrings.TryGetValue(index, out var value) && index < _reader.Length)
{
var stringsReader = _reader.ForkRelative(index);
value = stringsReader.ReadUtf8String();
_cachedStrings[index] = value;
}
return value;
}
/// <inheritdoc />
public override bool TryFindStringIndex(Utf8String? value, out uint index)
{
if (value is null)
{
index = 0;
return true;
}
byte[] bytes = value.GetBytesUnsafe();
var reader = _reader.Fork();
while (reader.CanRead((uint) value.ByteCount))
{
index = reader.RelativeOffset;
int i = 0;
for (; i < bytes.Length; i++)
{
if (bytes[i] != reader.ReadByte())
break;
}
if (i == value.Length && reader.CanRead(sizeof(byte)) && reader.ReadByte() == 0)
return true;
reader.RelativeOffset = index + 1;
}
index = 0;
return false;
}
}
}