Skip to content

Commit

Permalink
Encoding: Don't alloc for zero length array (dotnet#13794)
Browse files Browse the repository at this point in the history
  • Loading branch information
benaadams authored and jkotas committed Jan 2, 2018
1 parent a0d9f0f commit 0bb37fd
Show file tree
Hide file tree
Showing 8 changed files with 38 additions and 137 deletions.
21 changes: 5 additions & 16 deletions src/mscorlib/shared/System/Text/ASCIIEncoding.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace System.Text
{
Expand Down Expand Up @@ -130,11 +131,7 @@ public override unsafe int GetByteCount(char* chars, int count)

int byteCount = bytes.Length - byteIndex;

// Fixed doesn't like empty byte arrays
if (bytes.Length == 0)
bytes = new byte[1];

fixed (char* pChars = chars) fixed (byte* pBytes = &bytes[0])
fixed (char* pChars = chars) fixed (byte* pBytes = &MemoryMarshal.GetReference((Span<byte>)bytes))
return GetBytes(pChars + charIndex, charCount, pBytes + byteIndex, byteCount, null);
}

Expand Down Expand Up @@ -168,18 +165,14 @@ public override unsafe int GetByteCount(char* chars, int count)
if (byteIndex < 0 || byteIndex > bytes.Length)
throw new ArgumentOutOfRangeException("byteIndex", SR.ArgumentOutOfRange_Index);

// If nothing to encode return 0, avoid fixed problem
// If nothing to encode return 0
if (charCount == 0)
return 0;

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

// Fixed doesn't like empty byte arrays
if (bytes.Length == 0)
bytes = new byte[1];

fixed (char* pChars = chars) fixed (byte* pBytes = &bytes[0])
fixed (char* pChars = chars) fixed (byte* pBytes = &MemoryMarshal.GetReference((Span<byte>)bytes))
// Remember that byteCount is # to decode, not size of array.
return GetBytes(pChars + charIndex, charCount, pBytes + byteIndex, byteCount, null);
}
Expand Down Expand Up @@ -275,11 +268,7 @@ public override unsafe int GetCharCount(byte* bytes, int count)
// Just call pointer version
int charCount = chars.Length - charIndex;

// Fixed doesn't like empty char arrays
if (chars.Length == 0)
chars = new char[1];

fixed (byte* pBytes = bytes) fixed (char* pChars = &chars[0])
fixed (byte* pBytes = bytes) fixed (char* pChars = &MemoryMarshal.GetReference((Span<char>)chars))
// Remember that charCount is # to decode, not size of array
return GetChars(pBytes + byteIndex, byteCount, pChars + charIndex, charCount, null);
}
Expand Down
30 changes: 6 additions & 24 deletions src/mscorlib/shared/System/Text/DecoderNLS.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Runtime.Serialization;
using System.Text;
using System;
using System.Runtime.InteropServices;

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


// Avoid null fixed problem
if (bytes.Length == 0)
bytes = new byte[1];

// Just call pointer version
fixed (byte* pBytes = &bytes[0])
fixed (byte* pBytes = &MemoryMarshal.GetReference((Span<byte>)bytes))
return GetCharCount(pBytes + index, count, flush);
}

Expand Down Expand Up @@ -121,18 +117,11 @@ public unsafe override int GetCharCount(byte* bytes, int count, bool flush)
throw new ArgumentOutOfRangeException(nameof(charIndex),
SR.ArgumentOutOfRange_Index);


// Avoid empty input fixed problem
if (bytes.Length == 0)
bytes = new byte[1];

int charCount = chars.Length - charIndex;
if (chars.Length == 0)
chars = new char[1];

// Just call pointer version
fixed (byte* pBytes = &bytes[0])
fixed (char* pChars = &chars[0])
fixed (byte* pBytes = &MemoryMarshal.GetReference((Span<byte>)bytes))
fixed (char* pChars = &MemoryMarshal.GetReference((Span<char>)chars))
// Remember that charCount is # to decode, not size of array
return GetChars(pBytes + byteIndex, byteCount,
pChars + charIndex, charCount, flush);
Expand Down Expand Up @@ -185,17 +174,10 @@ public unsafe override int GetCharCount(byte* bytes, int count, bool flush)
throw new ArgumentOutOfRangeException(nameof(chars),
SR.ArgumentOutOfRange_IndexCountBuffer);


// Avoid empty input problem
if (bytes.Length == 0)
bytes = new byte[1];
if (chars.Length == 0)
chars = new char[1];

// Just call the pointer version (public overrides can't do this)
fixed (byte* pBytes = &bytes[0])
fixed (byte* pBytes = &MemoryMarshal.GetReference((Span<byte>)bytes))
{
fixed (char* pChars = &chars[0])
fixed (char* pChars = &MemoryMarshal.GetReference((Span<char>)chars))
{
Convert(pBytes + byteIndex, byteCount, pChars + charIndex, charCount, flush,
out bytesUsed, out charsUsed, out completed);
Expand Down
27 changes: 6 additions & 21 deletions src/mscorlib/shared/System/Text/EncoderNLS.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

using System.Text;
using System;
using System.Runtime.InteropServices;

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

// Avoid empty input problem
if (chars.Length == 0)
chars = new char[1];

// Just call the pointer version
int result = -1;
fixed (char* pChars = &chars[0])
fixed (char* pChars = &MemoryMarshal.GetReference((Span<char>)chars))
{
result = GetByteCount(pChars + index, count, flush);
}
Expand Down Expand Up @@ -112,16 +109,11 @@ public unsafe override int GetByteCount(char* chars, int count, bool flush)
throw new ArgumentOutOfRangeException(nameof(byteIndex),
SR.ArgumentOutOfRange_Index);

if (chars.Length == 0)
chars = new char[1];

int byteCount = bytes.Length - byteIndex;
if (bytes.Length == 0)
bytes = new byte[1];

// Just call pointer version
fixed (char* pChars = &chars[0])
fixed (byte* pBytes = &bytes[0])
fixed (char* pChars = &MemoryMarshal.GetReference((Span<char>)chars))
fixed (byte* pBytes = &MemoryMarshal.GetReference((Span<byte>)bytes))

// Remember that charCount is # to decode, not size of array.
return GetBytes(pChars + charIndex, charCount,
Expand Down Expand Up @@ -171,17 +163,10 @@ public unsafe override int GetBytes(char* chars, int charCount, byte* bytes, int
throw new ArgumentOutOfRangeException(nameof(bytes),
SR.ArgumentOutOfRange_IndexCountBuffer);


// Avoid empty input problem
if (chars.Length == 0)
chars = new char[1];
if (bytes.Length == 0)
bytes = new byte[1];

// Just call the pointer version (can't do this for non-msft encoders)
fixed (char* pChars = &chars[0])
fixed (char* pChars = &MemoryMarshal.GetReference((Span<char>)chars))
{
fixed (byte* pBytes = &bytes[0])
fixed (byte* pBytes = &MemoryMarshal.GetReference((Span<byte>)bytes))
{
Convert(pChars + charIndex, charCount, pBytes + byteIndex, byteCount, flush,
out charsUsed, out bytesUsed, out completed);
Expand Down
21 changes: 5 additions & 16 deletions src/mscorlib/shared/System/Text/EncodingNLS.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System;
using System.Collections;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Threading;

namespace System.Text
Expand Down Expand Up @@ -107,11 +108,7 @@ public override unsafe int GetByteCount(char* chars, int count)

int byteCount = bytes.Length - byteIndex;

// Fixed doesn't like empty arrays
if (bytes.Length == 0)
bytes = new byte[1];

fixed (char* pChars = s) fixed (byte* pBytes = &bytes[0])
fixed (char* pChars = s) fixed (byte* pBytes = &MemoryMarshal.GetReference((Span<byte>)bytes))
return GetBytes(pChars + charIndex, charCount, pBytes + byteIndex, byteCount, null);
}

Expand Down Expand Up @@ -151,13 +148,9 @@ public override unsafe int GetByteCount(char* chars, int count)
// Just call pointer version
int byteCount = bytes.Length - byteIndex;

// Fixed doesn't like empty arrays
if (bytes.Length == 0)
bytes = new byte[1];

fixed (char* pChars = chars) fixed (byte* pBytes = &bytes[0])
fixed (char* pChars = chars) fixed (byte* pBytes = &MemoryMarshal.GetReference((Span<byte>)bytes))
// Remember that byteCount is # to decode, not size of array.
return GetBytes(pChars + charIndex, charCount, pBytes + byteIndex, byteCount, null);
return GetBytes(pChars + charIndex, charCount, pBytes + byteIndex, byteCount, null);
}

// All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
Expand Down Expand Up @@ -245,11 +238,7 @@ public override unsafe int GetCharCount(byte* bytes, int count)
// Just call pointer version
int charCount = chars.Length - charIndex;

// Fixed doesn't like empty arrays
if (chars.Length == 0)
chars = new char[1];

fixed (byte* pBytes = bytes) fixed (char* pChars = &chars[0])
fixed (byte* pBytes = bytes) fixed (char* pChars = &MemoryMarshal.GetReference((Span<char>)chars))
// Remember that charCount is # to decode, not size of array
return GetChars(pBytes + byteIndex, byteCount, pChars + charIndex, charCount, null);
}
Expand Down
19 changes: 4 additions & 15 deletions src/mscorlib/shared/System/Text/UTF32Encoding.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using System;
using System.Diagnostics;
using System.Globalization;
using System.Runtime.InteropServices;

namespace System.Text
{
Expand Down Expand Up @@ -174,11 +175,7 @@ public override unsafe int GetByteCount(char* chars, int count)

int byteCount = bytes.Length - byteIndex;

// Fix our input array if 0 length because fixed doesn't like 0 length arrays
if (bytes.Length == 0)
bytes = new byte[1];

fixed (char* pChars = s) fixed (byte* pBytes = &bytes[0])
fixed (char* pChars = s) fixed (byte* pBytes = &MemoryMarshal.GetReference((Span<byte>)bytes))
return GetBytes(pChars + charIndex, charCount, pBytes + byteIndex, byteCount, null);
}

Expand Down Expand Up @@ -219,11 +216,7 @@ public override unsafe int GetByteCount(char* chars, int count)
// Just call pointer version
int byteCount = bytes.Length - byteIndex;

// Fix our input array if 0 length because fixed doesn't like 0 length arrays
if (bytes.Length == 0)
bytes = new byte[1];

fixed (char* pChars = chars) fixed (byte* pBytes = &bytes[0])
fixed (char* pChars = chars) fixed (byte* pBytes = &MemoryMarshal.GetReference((Span<byte>)bytes))
// Remember that byteCount is # to decode, not size of array.
return GetBytes(pChars + charIndex, charCount, pBytes + byteIndex, byteCount, null);
}
Expand Down Expand Up @@ -319,11 +312,7 @@ public override unsafe int GetCharCount(byte* bytes, int count)
// Just call pointer version
int charCount = chars.Length - charIndex;

// Fix our input array if 0 length because fixed doesn't like 0 length arrays
if (chars.Length == 0)
chars = new char[1];

fixed (byte* pBytes = bytes) fixed (char* pChars = &chars[0])
fixed (byte* pBytes = bytes) fixed (char* pChars = &MemoryMarshal.GetReference((Span<char>)chars))
// Remember that charCount is # to decode, not size of array
return GetChars(pBytes + byteIndex, byteCount, pChars + charIndex, charCount, null);
}
Expand Down
19 changes: 4 additions & 15 deletions src/mscorlib/shared/System/Text/UTF7Encoding.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace System.Text
{
Expand Down Expand Up @@ -204,11 +205,7 @@ public override unsafe int GetByteCount(char* chars, int count)

int byteCount = bytes.Length - byteIndex;

// Fixed doesn't like empty arrays
if (bytes.Length == 0)
bytes = new byte[1];

fixed (char* pChars = s) fixed (byte* pBytes = &bytes[0])
fixed (char* pChars = s) fixed (byte* pBytes = &MemoryMarshal.GetReference((Span<byte>)bytes))
return GetBytes(pChars + charIndex, charCount, pBytes + byteIndex, byteCount, null);
}

Expand Down Expand Up @@ -249,11 +246,7 @@ public override unsafe int GetByteCount(char* chars, int count)
// Just call pointer version
int byteCount = bytes.Length - byteIndex;

// Fixed doesn't like empty arrays
if (bytes.Length == 0)
bytes = new byte[1];

fixed (char* pChars = chars) fixed (byte* pBytes = &bytes[0])
fixed (char* pChars = chars) fixed (byte* pBytes = &MemoryMarshal.GetReference((Span<byte>)bytes))
// Remember that byteCount is # to decode, not size of array.
return GetBytes(pChars + charIndex, charCount, pBytes + byteIndex, byteCount, null);
}
Expand Down Expand Up @@ -349,11 +342,7 @@ public override unsafe int GetCharCount(byte* bytes, int count)
// Just call pointer version
int charCount = chars.Length - charIndex;

// Fixed doesn't like empty arrays
if (chars.Length == 0)
chars = new char[1];

fixed (byte* pBytes = bytes) fixed (char* pChars = &chars[0])
fixed (byte* pBytes = bytes) fixed (char* pChars = &MemoryMarshal.GetReference((Span<char>)chars))
// Remember that charCount is # to decode, not size of array
return GetChars(pBytes + byteIndex, byteCount, pChars + charIndex, charCount, null);
}
Expand Down
19 changes: 4 additions & 15 deletions src/mscorlib/shared/System/Text/UTF8Encoding.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
using System;
using System.Diagnostics;
using System.Globalization;
using System.Runtime.InteropServices;

namespace System.Text
{
Expand Down Expand Up @@ -201,11 +202,7 @@ public override unsafe int GetByteCount(char* chars, int count)

int byteCount = bytes.Length - byteIndex;

// Fixed doesn't like 0 length arrays.
if (bytes.Length == 0)
bytes = new byte[1];

fixed (char* pChars = s) fixed (byte* pBytes = &bytes[0])
fixed (char* pChars = s) fixed (byte* pBytes = &MemoryMarshal.GetReference((Span<byte>)bytes))
return GetBytes(pChars + charIndex, charCount, pBytes + byteIndex, byteCount, null);
}

Expand Down Expand Up @@ -246,11 +243,7 @@ public override unsafe int GetByteCount(char* chars, int count)
// Just call pointer version
int byteCount = bytes.Length - byteIndex;

// Fixed doesn't like 0 length arrays.
if (bytes.Length == 0)
bytes = new byte[1];

fixed (char* pChars = chars) fixed (byte* pBytes = &bytes[0])
fixed (char* pChars = chars) fixed (byte* pBytes = &MemoryMarshal.GetReference((Span<byte>)bytes))
// Remember that byteCount is # to decode, not size of array.
return GetBytes(pChars + charIndex, charCount, pBytes + byteIndex, byteCount, null);
}
Expand Down Expand Up @@ -346,11 +339,7 @@ public override unsafe int GetCharCount(byte* bytes, int count)
// Just call pointer version
int charCount = chars.Length - charIndex;

// Fixed doesn't like 0 length arrays.
if (chars.Length == 0)
chars = new char[1];

fixed (byte* pBytes = bytes) fixed (char* pChars = &chars[0])
fixed (byte* pBytes = bytes) fixed (char* pChars = &MemoryMarshal.GetReference((Span<char>)chars))
// Remember that charCount is # to decode, not size of array
return GetChars(pBytes + byteIndex, byteCount, pChars + charIndex, charCount, null);
}
Expand Down
Loading

0 comments on commit 0bb37fd

Please sign in to comment.