Skip to content

Commit 0bb37fd

Browse files
benaadamsjkotas
authored andcommitted
Encoding: Don't alloc for zero length array (dotnet#13794)
1 parent a0d9f0f commit 0bb37fd

File tree

8 files changed

+38
-137
lines changed

8 files changed

+38
-137
lines changed

src/mscorlib/shared/System/Text/ASCIIEncoding.cs

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
using System;
66
using System.Diagnostics;
7+
using System.Runtime.InteropServices;
78

89
namespace System.Text
910
{
@@ -130,11 +131,7 @@ public override unsafe int GetBytes(String chars, int charIndex, int charCount,
130131

131132
int byteCount = bytes.Length - byteIndex;
132133

133-
// Fixed doesn't like empty byte arrays
134-
if (bytes.Length == 0)
135-
bytes = new byte[1];
136-
137-
fixed (char* pChars = chars) fixed (byte* pBytes = &bytes[0])
134+
fixed (char* pChars = chars) fixed (byte* pBytes = &MemoryMarshal.GetReference((Span<byte>)bytes))
138135
return GetBytes(pChars + charIndex, charCount, pBytes + byteIndex, byteCount, null);
139136
}
140137

@@ -168,18 +165,14 @@ public override unsafe int GetBytes(char[] chars, int charIndex, int charCount,
168165
if (byteIndex < 0 || byteIndex > bytes.Length)
169166
throw new ArgumentOutOfRangeException("byteIndex", SR.ArgumentOutOfRange_Index);
170167

171-
// If nothing to encode return 0, avoid fixed problem
168+
// If nothing to encode return 0
172169
if (charCount == 0)
173170
return 0;
174171

175172
// Just call pointer version
176173
int byteCount = bytes.Length - byteIndex;
177174

178-
// Fixed doesn't like empty byte arrays
179-
if (bytes.Length == 0)
180-
bytes = new byte[1];
181-
182-
fixed (char* pChars = chars) fixed (byte* pBytes = &bytes[0])
175+
fixed (char* pChars = chars) fixed (byte* pBytes = &MemoryMarshal.GetReference((Span<byte>)bytes))
183176
// Remember that byteCount is # to decode, not size of array.
184177
return GetBytes(pChars + charIndex, charCount, pBytes + byteIndex, byteCount, null);
185178
}
@@ -275,11 +268,7 @@ public override unsafe int GetChars(byte[] bytes, int byteIndex, int byteCount,
275268
// Just call pointer version
276269
int charCount = chars.Length - charIndex;
277270

278-
// Fixed doesn't like empty char arrays
279-
if (chars.Length == 0)
280-
chars = new char[1];
281-
282-
fixed (byte* pBytes = bytes) fixed (char* pChars = &chars[0])
271+
fixed (byte* pBytes = bytes) fixed (char* pChars = &MemoryMarshal.GetReference((Span<char>)chars))
283272
// Remember that charCount is # to decode, not size of array
284273
return GetChars(pBytes + byteIndex, byteCount, pChars + charIndex, charCount, null);
285274
}

src/mscorlib/shared/System/Text/DecoderNLS.cs

Lines changed: 6 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System.Runtime.Serialization;
66
using System.Text;
77
using System;
8+
using System.Runtime.InteropServices;
89

910
namespace System.Text
1011
{
@@ -66,13 +67,8 @@ public override unsafe int GetCharCount(byte[] bytes, int index, int count, bool
6667
throw new ArgumentOutOfRangeException(nameof(bytes),
6768
SR.ArgumentOutOfRange_IndexCountBuffer);
6869

69-
70-
// Avoid null fixed problem
71-
if (bytes.Length == 0)
72-
bytes = new byte[1];
73-
7470
// Just call pointer version
75-
fixed (byte* pBytes = &bytes[0])
71+
fixed (byte* pBytes = &MemoryMarshal.GetReference((Span<byte>)bytes))
7672
return GetCharCount(pBytes + index, count, flush);
7773
}
7874

@@ -121,18 +117,11 @@ public override unsafe int GetChars(byte[] bytes, int byteIndex, int byteCount,
121117
throw new ArgumentOutOfRangeException(nameof(charIndex),
122118
SR.ArgumentOutOfRange_Index);
123119

124-
125-
// Avoid empty input fixed problem
126-
if (bytes.Length == 0)
127-
bytes = new byte[1];
128-
129120
int charCount = chars.Length - charIndex;
130-
if (chars.Length == 0)
131-
chars = new char[1];
132121

133122
// Just call pointer version
134-
fixed (byte* pBytes = &bytes[0])
135-
fixed (char* pChars = &chars[0])
123+
fixed (byte* pBytes = &MemoryMarshal.GetReference((Span<byte>)bytes))
124+
fixed (char* pChars = &MemoryMarshal.GetReference((Span<char>)chars))
136125
// Remember that charCount is # to decode, not size of array
137126
return GetChars(pBytes + byteIndex, byteCount,
138127
pChars + charIndex, charCount, flush);
@@ -185,17 +174,10 @@ public override unsafe void Convert(byte[] bytes, int byteIndex, int byteCount,
185174
throw new ArgumentOutOfRangeException(nameof(chars),
186175
SR.ArgumentOutOfRange_IndexCountBuffer);
187176

188-
189-
// Avoid empty input problem
190-
if (bytes.Length == 0)
191-
bytes = new byte[1];
192-
if (chars.Length == 0)
193-
chars = new char[1];
194-
195177
// Just call the pointer version (public overrides can't do this)
196-
fixed (byte* pBytes = &bytes[0])
178+
fixed (byte* pBytes = &MemoryMarshal.GetReference((Span<byte>)bytes))
197179
{
198-
fixed (char* pChars = &chars[0])
180+
fixed (char* pChars = &MemoryMarshal.GetReference((Span<char>)chars))
199181
{
200182
Convert(pBytes + byteIndex, byteCount, pChars + charIndex, charCount, flush,
201183
out bytesUsed, out charsUsed, out completed);

src/mscorlib/shared/System/Text/EncoderNLS.cs

Lines changed: 6 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
using System.Text;
66
using System;
7+
using System.Runtime.InteropServices;
78

89
namespace System.Text
910
{
@@ -63,13 +64,9 @@ public override unsafe int GetByteCount(char[] chars, int index, int count, bool
6364
throw new ArgumentOutOfRangeException(nameof(chars),
6465
SR.ArgumentOutOfRange_IndexCountBuffer);
6566

66-
// Avoid empty input problem
67-
if (chars.Length == 0)
68-
chars = new char[1];
69-
7067
// Just call the pointer version
7168
int result = -1;
72-
fixed (char* pChars = &chars[0])
69+
fixed (char* pChars = &MemoryMarshal.GetReference((Span<char>)chars))
7370
{
7471
result = GetByteCount(pChars + index, count, flush);
7572
}
@@ -112,16 +109,11 @@ public override unsafe int GetBytes(char[] chars, int charIndex, int charCount,
112109
throw new ArgumentOutOfRangeException(nameof(byteIndex),
113110
SR.ArgumentOutOfRange_Index);
114111

115-
if (chars.Length == 0)
116-
chars = new char[1];
117-
118112
int byteCount = bytes.Length - byteIndex;
119-
if (bytes.Length == 0)
120-
bytes = new byte[1];
121113

122114
// Just call pointer version
123-
fixed (char* pChars = &chars[0])
124-
fixed (byte* pBytes = &bytes[0])
115+
fixed (char* pChars = &MemoryMarshal.GetReference((Span<char>)chars))
116+
fixed (byte* pBytes = &MemoryMarshal.GetReference((Span<byte>)bytes))
125117

126118
// Remember that charCount is # to decode, not size of array.
127119
return GetBytes(pChars + charIndex, charCount,
@@ -171,17 +163,10 @@ public override unsafe void Convert(char[] chars, int charIndex, int charCount,
171163
throw new ArgumentOutOfRangeException(nameof(bytes),
172164
SR.ArgumentOutOfRange_IndexCountBuffer);
173165

174-
175-
// Avoid empty input problem
176-
if (chars.Length == 0)
177-
chars = new char[1];
178-
if (bytes.Length == 0)
179-
bytes = new byte[1];
180-
181166
// Just call the pointer version (can't do this for non-msft encoders)
182-
fixed (char* pChars = &chars[0])
167+
fixed (char* pChars = &MemoryMarshal.GetReference((Span<char>)chars))
183168
{
184-
fixed (byte* pBytes = &bytes[0])
169+
fixed (byte* pBytes = &MemoryMarshal.GetReference((Span<byte>)bytes))
185170
{
186171
Convert(pChars + charIndex, charCount, pBytes + byteIndex, byteCount, flush,
187172
out charsUsed, out bytesUsed, out completed);

src/mscorlib/shared/System/Text/EncodingNLS.cs

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System;
66
using System.Collections;
77
using System.Globalization;
8+
using System.Runtime.InteropServices;
89
using System.Threading;
910

1011
namespace System.Text
@@ -107,11 +108,7 @@ public override unsafe int GetBytes(String s, int charIndex, int charCount,
107108

108109
int byteCount = bytes.Length - byteIndex;
109110

110-
// Fixed doesn't like empty arrays
111-
if (bytes.Length == 0)
112-
bytes = new byte[1];
113-
114-
fixed (char* pChars = s) fixed (byte* pBytes = &bytes[0])
111+
fixed (char* pChars = s) fixed (byte* pBytes = &MemoryMarshal.GetReference((Span<byte>)bytes))
115112
return GetBytes(pChars + charIndex, charCount, pBytes + byteIndex, byteCount, null);
116113
}
117114

@@ -151,13 +148,9 @@ public override unsafe int GetBytes(char[] chars, int charIndex, int charCount,
151148
// Just call pointer version
152149
int byteCount = bytes.Length - byteIndex;
153150

154-
// Fixed doesn't like empty arrays
155-
if (bytes.Length == 0)
156-
bytes = new byte[1];
157-
158-
fixed (char* pChars = chars) fixed (byte* pBytes = &bytes[0])
151+
fixed (char* pChars = chars) fixed (byte* pBytes = &MemoryMarshal.GetReference((Span<byte>)bytes))
159152
// Remember that byteCount is # to decode, not size of array.
160-
return GetBytes(pChars + charIndex, charCount, pBytes + byteIndex, byteCount, null);
153+
return GetBytes(pChars + charIndex, charCount, pBytes + byteIndex, byteCount, null);
161154
}
162155

163156
// All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
@@ -245,11 +238,7 @@ public override unsafe int GetChars(byte[] bytes, int byteIndex, int byteCount,
245238
// Just call pointer version
246239
int charCount = chars.Length - charIndex;
247240

248-
// Fixed doesn't like empty arrays
249-
if (chars.Length == 0)
250-
chars = new char[1];
251-
252-
fixed (byte* pBytes = bytes) fixed (char* pChars = &chars[0])
241+
fixed (byte* pBytes = bytes) fixed (char* pChars = &MemoryMarshal.GetReference((Span<char>)chars))
253242
// Remember that charCount is # to decode, not size of array
254243
return GetChars(pBytes + byteIndex, byteCount, pChars + charIndex, charCount, null);
255244
}

src/mscorlib/shared/System/Text/UTF32Encoding.cs

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
using System;
1010
using System.Diagnostics;
1111
using System.Globalization;
12+
using System.Runtime.InteropServices;
1213

1314
namespace System.Text
1415
{
@@ -174,11 +175,7 @@ public override unsafe int GetBytes(String s, int charIndex, int charCount,
174175

175176
int byteCount = bytes.Length - byteIndex;
176177

177-
// Fix our input array if 0 length because fixed doesn't like 0 length arrays
178-
if (bytes.Length == 0)
179-
bytes = new byte[1];
180-
181-
fixed (char* pChars = s) fixed (byte* pBytes = &bytes[0])
178+
fixed (char* pChars = s) fixed (byte* pBytes = &MemoryMarshal.GetReference((Span<byte>)bytes))
182179
return GetBytes(pChars + charIndex, charCount, pBytes + byteIndex, byteCount, null);
183180
}
184181

@@ -219,11 +216,7 @@ public override unsafe int GetBytes(char[] chars, int charIndex, int charCount,
219216
// Just call pointer version
220217
int byteCount = bytes.Length - byteIndex;
221218

222-
// Fix our input array if 0 length because fixed doesn't like 0 length arrays
223-
if (bytes.Length == 0)
224-
bytes = new byte[1];
225-
226-
fixed (char* pChars = chars) fixed (byte* pBytes = &bytes[0])
219+
fixed (char* pChars = chars) fixed (byte* pBytes = &MemoryMarshal.GetReference((Span<byte>)bytes))
227220
// Remember that byteCount is # to decode, not size of array.
228221
return GetBytes(pChars + charIndex, charCount, pBytes + byteIndex, byteCount, null);
229222
}
@@ -319,11 +312,7 @@ public override unsafe int GetChars(byte[] bytes, int byteIndex, int byteCount,
319312
// Just call pointer version
320313
int charCount = chars.Length - charIndex;
321314

322-
// Fix our input array if 0 length because fixed doesn't like 0 length arrays
323-
if (chars.Length == 0)
324-
chars = new char[1];
325-
326-
fixed (byte* pBytes = bytes) fixed (char* pChars = &chars[0])
315+
fixed (byte* pBytes = bytes) fixed (char* pChars = &MemoryMarshal.GetReference((Span<char>)chars))
327316
// Remember that charCount is # to decode, not size of array
328317
return GetChars(pBytes + byteIndex, byteCount, pChars + charIndex, charCount, null);
329318
}

src/mscorlib/shared/System/Text/UTF7Encoding.cs

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
using System;
1010
using System.Diagnostics;
11+
using System.Runtime.InteropServices;
1112

1213
namespace System.Text
1314
{
@@ -204,11 +205,7 @@ public override unsafe int GetBytes(string s, int charIndex, int charCount,
204205

205206
int byteCount = bytes.Length - byteIndex;
206207

207-
// Fixed doesn't like empty arrays
208-
if (bytes.Length == 0)
209-
bytes = new byte[1];
210-
211-
fixed (char* pChars = s) fixed (byte* pBytes = &bytes[0])
208+
fixed (char* pChars = s) fixed (byte* pBytes = &MemoryMarshal.GetReference((Span<byte>)bytes))
212209
return GetBytes(pChars + charIndex, charCount, pBytes + byteIndex, byteCount, null);
213210
}
214211

@@ -249,11 +246,7 @@ public override unsafe int GetBytes(char[] chars, int charIndex, int charCount,
249246
// Just call pointer version
250247
int byteCount = bytes.Length - byteIndex;
251248

252-
// Fixed doesn't like empty arrays
253-
if (bytes.Length == 0)
254-
bytes = new byte[1];
255-
256-
fixed (char* pChars = chars) fixed (byte* pBytes = &bytes[0])
249+
fixed (char* pChars = chars) fixed (byte* pBytes = &MemoryMarshal.GetReference((Span<byte>)bytes))
257250
// Remember that byteCount is # to decode, not size of array.
258251
return GetBytes(pChars + charIndex, charCount, pBytes + byteIndex, byteCount, null);
259252
}
@@ -349,11 +342,7 @@ public override unsafe int GetChars(byte[] bytes, int byteIndex, int byteCount,
349342
// Just call pointer version
350343
int charCount = chars.Length - charIndex;
351344

352-
// Fixed doesn't like empty arrays
353-
if (chars.Length == 0)
354-
chars = new char[1];
355-
356-
fixed (byte* pBytes = bytes) fixed (char* pChars = &chars[0])
345+
fixed (byte* pBytes = bytes) fixed (char* pChars = &MemoryMarshal.GetReference((Span<char>)chars))
357346
// Remember that charCount is # to decode, not size of array
358347
return GetChars(pBytes + byteIndex, byteCount, pChars + charIndex, charCount, null);
359348
}

src/mscorlib/shared/System/Text/UTF8Encoding.cs

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
using System;
1818
using System.Diagnostics;
1919
using System.Globalization;
20+
using System.Runtime.InteropServices;
2021

2122
namespace System.Text
2223
{
@@ -201,11 +202,7 @@ public override unsafe int GetBytes(String s, int charIndex, int charCount,
201202

202203
int byteCount = bytes.Length - byteIndex;
203204

204-
// Fixed doesn't like 0 length arrays.
205-
if (bytes.Length == 0)
206-
bytes = new byte[1];
207-
208-
fixed (char* pChars = s) fixed (byte* pBytes = &bytes[0])
205+
fixed (char* pChars = s) fixed (byte* pBytes = &MemoryMarshal.GetReference((Span<byte>)bytes))
209206
return GetBytes(pChars + charIndex, charCount, pBytes + byteIndex, byteCount, null);
210207
}
211208

@@ -246,11 +243,7 @@ public override unsafe int GetBytes(char[] chars, int charIndex, int charCount,
246243
// Just call pointer version
247244
int byteCount = bytes.Length - byteIndex;
248245

249-
// Fixed doesn't like 0 length arrays.
250-
if (bytes.Length == 0)
251-
bytes = new byte[1];
252-
253-
fixed (char* pChars = chars) fixed (byte* pBytes = &bytes[0])
246+
fixed (char* pChars = chars) fixed (byte* pBytes = &MemoryMarshal.GetReference((Span<byte>)bytes))
254247
// Remember that byteCount is # to decode, not size of array.
255248
return GetBytes(pChars + charIndex, charCount, pBytes + byteIndex, byteCount, null);
256249
}
@@ -346,11 +339,7 @@ public override unsafe int GetChars(byte[] bytes, int byteIndex, int byteCount,
346339
// Just call pointer version
347340
int charCount = chars.Length - charIndex;
348341

349-
// Fixed doesn't like 0 length arrays.
350-
if (chars.Length == 0)
351-
chars = new char[1];
352-
353-
fixed (byte* pBytes = bytes) fixed (char* pChars = &chars[0])
342+
fixed (byte* pBytes = bytes) fixed (char* pChars = &MemoryMarshal.GetReference((Span<char>)chars))
354343
// Remember that charCount is # to decode, not size of array
355344
return GetChars(pBytes + byteIndex, byteCount, pChars + charIndex, charCount, null);
356345
}

0 commit comments

Comments
 (0)