77using System . Collections . Generic ;
88using System . ComponentModel ;
99using System . Diagnostics ;
10+ using System . Reflection ;
1011using System . Runtime . CompilerServices ;
1112
1213namespace LibObjectFile . PE ;
@@ -17,20 +18,81 @@ namespace LibObjectFile.PE;
1718[ DebuggerDisplay ( $ "{ nameof ( PEDirectoryTable ) } { nameof ( Count ) } = {{{nameof(Count)}}}") ]
1819public sealed class PEDirectoryTable : IEnumerable < PEDataDirectory >
1920{
20- private InternalArray _entries ;
21+ private PEObjectBase ? [ ] _entries ;
2122 private int _count ;
2223
2324 internal PEDirectoryTable ( )
2425 {
26+ _entries = [ ] ;
2527 }
2628
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+ }
2846
2947 /// <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"/> .
3149 /// </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+
3496 /// <summary>
3597 /// Gets the export directory information from the PE file.
3698 /// </summary>
@@ -112,60 +174,23 @@ internal PEDirectoryTable()
112174 [ EditorBrowsable ( EditorBrowsableState . Never ) ]
113175 public Enumerator GetEnumerator ( ) => new ( this ) ;
114176
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 ) ;
121178
122- if ( previousEntry is not null )
123- {
124- _count -- ;
125- }
179+ internal void Set ( PEDataDirectoryKind kind , PEObjectBase ? directory ) => Set ( ( int ) kind , directory ) ;
126180
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 )
134182 {
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 )
140184 {
141- _count -- ;
185+ throw new ArgumentOutOfRangeException ( nameof ( index ) , $ "The directory entry only accepts { Count } entries. Set the count explicitly to allow more entries." ) ;
142186 }
143187
144- if ( directory is not null )
145- {
146- _count ++ ;
147- }
188+ _entries [ index ] = directory ;
148189 }
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+
165191 internal unsafe void Write ( PEImageWriter writer , ref uint position )
166192 {
167- var numberOfEntries = CalculateNumberOfEntries ( ) ;
168- for ( int i = 0 ; i < numberOfEntries ; i ++ )
193+ for ( int i = 0 ; i < Count ; i ++ )
169194 {
170195 ImageDataDirectory rawDataDirectory = default ;
171196 var entry = _entries [ i ] ;
@@ -176,13 +201,7 @@ internal unsafe void Write(PEImageWriter writer, ref uint position)
176201 }
177202 }
178203
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 ) ) ;
186205 }
187206
188207 /// <summary>
0 commit comments