1
1
// Copyright (c) Drew Noakes and contributors. All Rights Reserved. Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
2
2
3
+ using System . Buffers . Binary ;
4
+
3
5
namespace MetadataExtractor . IO
4
6
{
5
7
/// <summary>Base class for reading sequentially through a sequence of data encoded in a byte stream.</summary>
@@ -13,13 +15,8 @@ namespace MetadataExtractor.IO
13
15
/// <see cref="IsMotorolaByteOrder"/>.
14
16
/// </remarks>
15
17
/// <author>Drew Noakes https://drewnoakes.com</author>
16
- public abstract class SequentialReader
18
+ public abstract class SequentialReader ( bool isMotorolaByteOrder )
17
19
{
18
- protected SequentialReader ( bool isMotorolaByteOrder )
19
- {
20
- IsMotorolaByteOrder = isMotorolaByteOrder ;
21
- }
22
-
23
20
/// <summary>Get and set the byte order of this reader. <c>true</c> by default.</summary>
24
21
/// <remarks>
25
22
/// <list type="bullet">
@@ -28,7 +25,7 @@ protected SequentialReader(bool isMotorolaByteOrder)
28
25
/// </list>
29
26
/// </remarks>
30
27
/// <value><c>true</c> for Motorola/big endian, <c>false</c> for Intel/little endian</value>
31
- public bool IsMotorolaByteOrder { get ; }
28
+ public bool IsMotorolaByteOrder { get ; } = isMotorolaByteOrder ;
32
29
33
30
public abstract long Position { get ; }
34
31
@@ -40,6 +37,8 @@ protected SequentialReader(bool isMotorolaByteOrder)
40
37
/// <exception cref="IOException"/>
41
38
public abstract byte [ ] GetBytes ( int count ) ;
42
39
40
+ public abstract void GetBytes ( Span < byte > bytes ) ;
41
+
43
42
/// <summary>Retrieves bytes, writing them into a caller-provided buffer.</summary>
44
43
/// <param name="buffer">The array to write bytes to.</param>
45
44
/// <param name="offset">The starting position within <paramref name="buffer"/> to write to.</param>
@@ -100,139 +99,81 @@ protected SequentialReader(bool isMotorolaByteOrder)
100
99
/// <exception cref="IOException"/>
101
100
public ushort GetUInt16 ( )
102
101
{
103
- if ( IsMotorolaByteOrder )
104
- {
105
- // Motorola - MSB first
106
- return ( ushort )
107
- ( GetByte ( ) << 8 |
108
- GetByte ( ) ) ;
109
- }
110
- // Intel ordering - LSB first
111
- return ( ushort )
112
- ( GetByte ( ) |
113
- GetByte ( ) << 8 ) ;
102
+ Span < byte > bytes = stackalloc byte [ 2 ] ;
103
+
104
+ GetBytes ( bytes ) ;
105
+
106
+ return IsMotorolaByteOrder
107
+ ? BinaryPrimitives . ReadUInt16BigEndian ( bytes )
108
+ : BinaryPrimitives . ReadUInt16LittleEndian ( bytes ) ;
114
109
}
115
110
116
111
/// <summary>Returns a signed 16-bit int calculated from two bytes of data (MSB, LSB).</summary>
117
112
/// <returns>the 16 bit int value, between 0x0000 and 0xFFFF</returns>
118
113
/// <exception cref="IOException">the buffer does not contain enough bytes to service the request</exception>
119
114
public short GetInt16 ( )
120
115
{
121
- if ( IsMotorolaByteOrder )
122
- {
123
- // Motorola - MSB first
124
- return ( short )
125
- ( GetByte ( ) << 8 |
126
- GetByte ( ) ) ;
127
- }
128
- // Intel ordering - LSB first
129
- return ( short )
130
- ( GetByte ( ) |
131
- GetByte ( ) << 8 ) ;
116
+ Span < byte > bytes = stackalloc byte [ 2 ] ;
117
+
118
+ GetBytes ( bytes ) ;
119
+
120
+ return IsMotorolaByteOrder
121
+ ? BinaryPrimitives . ReadInt16BigEndian ( bytes )
122
+ : BinaryPrimitives . ReadInt16LittleEndian ( bytes ) ;
132
123
}
133
124
134
125
/// <summary>Get a 32-bit unsigned integer from the buffer, returning it as a long.</summary>
135
126
/// <returns>the unsigned 32-bit int value as a long, between 0x00000000 and 0xFFFFFFFF</returns>
136
127
/// <exception cref="IOException">the buffer does not contain enough bytes to service the request</exception>
137
128
public uint GetUInt32 ( )
138
129
{
139
- if ( IsMotorolaByteOrder )
140
- {
141
- // Motorola - MSB first (big endian)
142
- return ( uint )
143
- ( GetByte ( ) << 24 |
144
- GetByte ( ) << 16 |
145
- GetByte ( ) << 8 |
146
- GetByte ( ) ) ;
147
- }
148
- // Intel ordering - LSB first (little endian)
149
- return ( uint )
150
- ( GetByte ( ) |
151
- GetByte ( ) << 8 |
152
- GetByte ( ) << 16 |
153
- GetByte ( ) << 24 ) ;
130
+ Span < byte > bytes = stackalloc byte [ 4 ] ;
131
+
132
+ GetBytes ( bytes ) ;
133
+
134
+ return IsMotorolaByteOrder
135
+ ? BinaryPrimitives . ReadUInt32BigEndian ( bytes )
136
+ : BinaryPrimitives . ReadUInt32LittleEndian ( bytes ) ;
154
137
}
155
138
156
139
/// <summary>Returns a signed 32-bit integer from four bytes of data.</summary>
157
140
/// <returns>the signed 32 bit int value, between 0x00000000 and 0xFFFFFFFF</returns>
158
141
/// <exception cref="IOException">the buffer does not contain enough bytes to service the request</exception>
159
142
public int GetInt32 ( )
160
143
{
161
- if ( IsMotorolaByteOrder )
162
- {
163
- // Motorola - MSB first (big endian)
164
- return
165
- GetByte ( ) << 24 |
166
- GetByte ( ) << 16 |
167
- GetByte ( ) << 8 |
168
- GetByte ( ) ;
169
- }
170
- // Intel ordering - LSB first (little endian)
171
- return
172
- GetByte ( ) |
173
- GetByte ( ) << 8 |
174
- GetByte ( ) << 16 |
175
- GetByte ( ) << 24 ;
144
+ Span < byte > bytes = stackalloc byte [ 4 ] ;
145
+
146
+ GetBytes ( bytes ) ;
147
+
148
+ return IsMotorolaByteOrder
149
+ ? BinaryPrimitives . ReadInt32BigEndian ( bytes )
150
+ : BinaryPrimitives . ReadInt32LittleEndian ( bytes ) ;
176
151
}
177
152
178
153
/// <summary>Get a signed 64-bit integer from the buffer.</summary>
179
154
/// <returns>the 64 bit int value, between 0x0000000000000000 and 0xFFFFFFFFFFFFFFFF</returns>
180
155
/// <exception cref="IOException">the buffer does not contain enough bytes to service the request</exception>
181
156
public long GetInt64 ( )
182
157
{
183
- if ( IsMotorolaByteOrder )
184
- {
185
- // Motorola - MSB first
186
- return
187
- ( long ) GetByte ( ) << 56 |
188
- ( long ) GetByte ( ) << 48 |
189
- ( long ) GetByte ( ) << 40 |
190
- ( long ) GetByte ( ) << 32 |
191
- ( long ) GetByte ( ) << 24 |
192
- ( long ) GetByte ( ) << 16 |
193
- ( long ) GetByte ( ) << 8 |
194
- GetByte ( ) ;
195
- }
196
- // Intel ordering - LSB first
197
- return
198
- GetByte ( ) |
199
- ( long ) GetByte ( ) << 8 |
200
- ( long ) GetByte ( ) << 16 |
201
- ( long ) GetByte ( ) << 24 |
202
- ( long ) GetByte ( ) << 32 |
203
- ( long ) GetByte ( ) << 40 |
204
- ( long ) GetByte ( ) << 48 |
205
- ( long ) GetByte ( ) << 56 ;
158
+ Span < byte > bytes = stackalloc byte [ 8 ] ;
159
+ GetBytes ( bytes ) ;
160
+
161
+ return IsMotorolaByteOrder
162
+ ? BinaryPrimitives . ReadInt64BigEndian ( bytes )
163
+ : BinaryPrimitives . ReadInt64LittleEndian ( bytes ) ;
206
164
}
207
165
208
166
/// <summary>Get an unsigned 64-bit integer from the buffer.</summary>
209
167
/// <returns>the unsigned 64 bit int value, between 0x0000000000000000 and 0xFFFFFFFFFFFFFFFF</returns>
210
168
/// <exception cref="IOException">the buffer does not contain enough bytes to service the request</exception>
211
169
public ulong GetUInt64 ( )
212
170
{
213
- if ( IsMotorolaByteOrder )
214
- {
215
- // Motorola - MSB first
216
- return
217
- ( ulong ) GetByte ( ) << 56 |
218
- ( ulong ) GetByte ( ) << 48 |
219
- ( ulong ) GetByte ( ) << 40 |
220
- ( ulong ) GetByte ( ) << 32 |
221
- ( ulong ) GetByte ( ) << 24 |
222
- ( ulong ) GetByte ( ) << 16 |
223
- ( ulong ) GetByte ( ) << 8 |
224
- GetByte ( ) ;
225
- }
226
- // Intel ordering - LSB first
227
- return
228
- GetByte ( ) |
229
- ( ulong ) GetByte ( ) << 8 |
230
- ( ulong ) GetByte ( ) << 16 |
231
- ( ulong ) GetByte ( ) << 24 |
232
- ( ulong ) GetByte ( ) << 32 |
233
- ( ulong ) GetByte ( ) << 40 |
234
- ( ulong ) GetByte ( ) << 48 |
235
- ( ulong ) GetByte ( ) << 56 ;
171
+ Span < byte > bytes = stackalloc byte [ 8 ] ;
172
+ GetBytes ( bytes ) ;
173
+
174
+ return IsMotorolaByteOrder
175
+ ? BinaryPrimitives . ReadUInt64BigEndian ( bytes )
176
+ : BinaryPrimitives . ReadUInt64LittleEndian ( bytes ) ;
236
177
}
237
178
238
179
#pragma warning restore format
@@ -271,8 +212,14 @@ public float GetS15Fixed16()
271
212
/// <exception cref="IOException"/>
272
213
public string GetString ( int bytesRequested , Encoding encoding )
273
214
{
215
+ #if NETSTANDARD2_1
216
+ Span < byte > bytes = bytesRequested > 2048 ? new byte [ bytesRequested ] : stackalloc byte [ bytesRequested ] ;
217
+ GetBytes ( bytes ) ;
218
+ return encoding . GetString ( bytes ) ;
219
+ #else
274
220
var bytes = GetBytes ( bytesRequested ) ;
275
221
return encoding . GetString ( bytes , 0 , bytes . Length ) ;
222
+ #endif
276
223
}
277
224
278
225
public StringValue GetStringValue ( int bytesRequested , Encoding ? encoding = null )
0 commit comments