7
7
using System . Collections . Generic ;
8
8
using System . ComponentModel ;
9
9
using System . Diagnostics ;
10
+ using System . Reflection ;
10
11
using System . Runtime . CompilerServices ;
11
12
12
13
namespace LibObjectFile . PE ;
@@ -17,20 +18,81 @@ namespace LibObjectFile.PE;
17
18
[ DebuggerDisplay ( $ "{ nameof ( PEDirectoryTable ) } { nameof ( Count ) } = {{{nameof(Count)}}}") ]
18
19
public sealed class PEDirectoryTable : IEnumerable < PEDataDirectory >
19
20
{
20
- private InternalArray _entries ;
21
+ private PEObjectBase ? [ ] _entries ;
21
22
private int _count ;
22
23
23
24
internal PEDirectoryTable ( )
24
25
{
26
+ _entries = [ ] ;
25
27
}
26
28
27
- public PEObjectBase ? this [ PEDataDirectoryKind kind ] => _entries [ ( int ) kind ] ;
29
+ /// <summary>
30
+ /// Gets the directory entry at the specified index.
31
+ /// </summary>
32
+ /// <param name="index">The index of the directory entry to get.</param>
33
+ /// <returns>The directory entry at the specified index.</returns>
34
+ /// <exception cref="ArgumentOutOfRangeException">Thrown if the index is out of range.</exception>
35
+ public PEObjectBase ? this [ int index ]
36
+ {
37
+ get
38
+ {
39
+ if ( index < 0 || index >= _count )
40
+ {
41
+ throw new ArgumentOutOfRangeException ( nameof ( index ) ) ;
42
+ }
43
+ return _entries [ index ] ;
44
+ }
45
+ }
28
46
29
47
/// <summary>
30
- /// Gets the number of directory entries in the array .
48
+ /// Gets the directory entry of the specified kind. Must be within the bounds of <see cref="Count"/> .
31
49
/// </summary>
32
- public int Count => _count ;
33
-
50
+ /// <param name="kind">The kind of directory entry to get.</param>
51
+ /// <returns></returns>
52
+ /// <exception cref="ArgumentOutOfRangeException">Thrown if the kind is out of range.</exception>
53
+ public PEObjectBase ? this [ PEDataDirectoryKind kind ]
54
+ {
55
+ get
56
+ {
57
+ int index = ( int ) ( ushort ) kind ;
58
+ if ( index < 0 || index >= _count )
59
+ {
60
+ throw new ArgumentOutOfRangeException ( nameof ( kind ) ) ;
61
+ }
62
+ return _entries [ ( int ) kind ] ;
63
+ }
64
+ }
65
+
66
+ /// <summary>
67
+ /// Gets the maximum number of directory entries in the array.
68
+ /// </summary>
69
+ public int Count
70
+ {
71
+ get => _count ;
72
+
73
+ set
74
+ {
75
+ ArgumentOutOfRangeException . ThrowIfLessThan ( value , 0 ) ;
76
+
77
+ var previousCount = _count ;
78
+ // If the count is reduced, we need to check that all entries are null after
79
+ for ( int i = value ; i < previousCount ; i ++ )
80
+ {
81
+ if ( _entries [ i ] is not null )
82
+ {
83
+ throw new ArgumentOutOfRangeException ( nameof ( value ) , $ "A non null directory entry was found at index { i } . This directory entry must be removed before setting a count of { value } ") ;
84
+ }
85
+ }
86
+
87
+ if ( _entries . Length < value )
88
+ {
89
+ Array . Resize ( ref _entries , value ) ;
90
+ }
91
+
92
+ _count = value ;
93
+ }
94
+ }
95
+
34
96
/// <summary>
35
97
/// Gets the export directory information from the PE file.
36
98
/// </summary>
@@ -112,60 +174,23 @@ internal PEDirectoryTable()
112
174
[ EditorBrowsable ( EditorBrowsableState . Never ) ]
113
175
public Enumerator GetEnumerator ( ) => new ( this ) ;
114
176
115
- internal void Set ( PESecurityCertificateDirectory ? directory )
116
- {
117
- var kind = PEDataDirectoryKind . SecurityCertificate ;
118
- ref var entry = ref _entries [ ( int ) kind ] ;
119
- var previousEntry = entry ;
120
- entry = directory ;
177
+ internal void Set ( PESecurityCertificateDirectory ? directory ) => Set ( PEDataDirectoryKind . SecurityCertificate , directory ) ;
121
178
122
- if ( previousEntry is not null )
123
- {
124
- _count -- ;
125
- }
179
+ internal void Set ( PEDataDirectoryKind kind , PEObjectBase ? directory ) => Set ( ( int ) kind , directory ) ;
126
180
127
- if ( directory is not null )
128
- {
129
- _count ++ ;
130
- }
131
- }
132
-
133
- internal void Set ( PEDataDirectoryKind kind , PEDataDirectory ? directory )
181
+ internal void Set ( int index , PEObjectBase ? directory )
134
182
{
135
- ref var entry = ref _entries [ ( int ) kind ] ;
136
- var previousEntry = entry ;
137
- entry = directory ;
138
-
139
- if ( previousEntry is not null )
183
+ if ( index >= Count )
140
184
{
141
- _count -- ;
185
+ throw new ArgumentOutOfRangeException ( nameof ( index ) , $ "The directory entry only accepts { Count } entries. Set the count explicitly to allow more entries." ) ;
142
186
}
143
187
144
- if ( directory is not null )
145
- {
146
- _count ++ ;
147
- }
188
+ _entries [ index ] = directory ;
148
189
}
149
-
150
- internal int CalculateNumberOfEntries ( )
151
- {
152
- int count = 0 ;
153
- ReadOnlySpan < PEObjectBase ? > span = _entries ;
154
- for ( int i = 0 ; i < span . Length ; i ++ )
155
- {
156
- if ( _entries [ i ] is not null )
157
- {
158
- count = i + 1 ;
159
- }
160
- }
161
-
162
- return count ;
163
- }
164
-
190
+
165
191
internal unsafe void Write ( PEImageWriter writer , ref uint position )
166
192
{
167
- var numberOfEntries = CalculateNumberOfEntries ( ) ;
168
- for ( int i = 0 ; i < numberOfEntries ; i ++ )
193
+ for ( int i = 0 ; i < Count ; i ++ )
169
194
{
170
195
ImageDataDirectory rawDataDirectory = default ;
171
196
var entry = _entries [ i ] ;
@@ -176,13 +201,7 @@ internal unsafe void Write(PEImageWriter writer, ref uint position)
176
201
}
177
202
}
178
203
179
- position += ( uint ) ( numberOfEntries * sizeof ( ImageDataDirectory ) ) ;
180
- }
181
-
182
- [ InlineArray ( 15 ) ]
183
- private struct InternalArray
184
- {
185
- private PEObjectBase ? _element ;
204
+ position += ( uint ) ( Count * sizeof ( ImageDataDirectory ) ) ;
186
205
}
187
206
188
207
/// <summary>
0 commit comments