Skip to content

Commit 2e8f025

Browse files
committed
Update the downlevel WriteUtf8 to use unsafe code.
1 parent 82bd703 commit 2e8f025

File tree

1 file changed

+47
-47
lines changed
  • src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities

1 file changed

+47
-47
lines changed

src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/BlobUtilities.cs

Lines changed: 47 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -157,74 +157,74 @@ public static void WriteUtf8(ReadOnlySpan<char> source, Span<byte> destination,
157157
bytesWritten = destinationLength - destination.Length;
158158
}
159159
#else
160-
public static void WriteUtf8(ReadOnlySpan<char> source, Span<byte> destination, out int charsRead, out int bytesWritten, bool allowUnpairedSurrogates)
160+
public static unsafe void WriteUtf8(ReadOnlySpan<char> source, Span<byte> destination, out int charsRead, out int bytesWritten, bool allowUnpairedSurrogates)
161161
{
162162
const char ReplacementCharacter = '\uFFFD';
163163

164164
int sourceLength = source.Length;
165165
int destinationLength = destination.Length;
166166

167-
while (!source.IsEmpty)
167+
fixed (char* pSource = &MemoryMarshal.GetReference(source))
168+
fixed (byte* pDestination = &MemoryMarshal.GetReference(destination))
168169
{
169-
char c = source[0];
170-
if (c < 0x80)
170+
char* src = pSource, srcEnd = pSource + source.Length;
171+
byte* dst = pDestination, dstEnd = pDestination + destination.Length;
172+
173+
while (src < srcEnd)
171174
{
172-
if (destination.Length < 1)
175+
char c = *src++;
176+
if (c < 0x80)
173177
{
174-
break;
178+
if (dstEnd - dst < 1)
179+
{
180+
break;
181+
}
182+
*dst++ = (byte)c;
175183
}
176-
destination[0] = (byte)c;
177-
destination = destination.Slice(1);
178-
source = source.Slice(1);
179-
}
180-
else if (c < 0x7FF)
181-
{
182-
if (destination.Length < 2)
184+
else if (c < 0x7FF)
183185
{
184-
break;
186+
if (dstEnd - dst < 2)
187+
{
188+
break;
189+
}
190+
*dst++ = (byte)((c >> 6) | 0xC0);
191+
*dst++ = (byte)((c & 0x3F) | 0x80);
185192
}
186-
destination[0] = (byte)((c >> 6) | 0xC0);
187-
destination[1] = (byte)((c & 0x3F) | 0x80);
188-
destination = destination.Slice(2);
189-
source = source.Slice(1);
190-
}
191-
else
192-
{
193-
if (char.IsSurrogate(c))
193+
else
194194
{
195-
// surrogate pair
196-
if (char.IsHighSurrogate(c) && source.Length > 1 && source[1] is char cLow && char.IsLowSurrogate(cLow))
195+
if (char.IsSurrogate(c))
197196
{
198-
if (destination.Length < 4)
197+
// surrogate pair
198+
if (char.IsHighSurrogate(c) && src < srcEnd && *src is char cLow && char.IsLowSurrogate(cLow))
199+
{
200+
src++;
201+
if (dstEnd - dst < 4)
202+
{
203+
break;
204+
}
205+
int codepoint = ((c - 0xd800) << 10) + cLow - 0xdc00 + 0x10000;
206+
*dst++ = (byte)((codepoint >> 18) | 0xF0);
207+
*dst++ = (byte)(((codepoint >> 12) & 0x3F) | 0x80);
208+
*dst++ = (byte)(((codepoint >> 6) & 0x3F) | 0x80);
209+
*dst++ = (byte)((codepoint & 0x3F) | 0x80);
210+
continue;
211+
}
212+
213+
// unpaired high/low surrogate
214+
if (!allowUnpairedSurrogates)
199215
{
200-
break;
216+
c = ReplacementCharacter;
201217
}
202-
int codepoint = ((c - 0xd800) << 10) + cLow - 0xdc00 + 0x10000;
203-
destination[0] = (byte)((codepoint >> 18) | 0xF0);
204-
destination[1] = (byte)(((codepoint >> 12) & 0x3F) | 0x80);
205-
destination[2] = (byte)(((codepoint >> 6) & 0x3F) | 0x80);
206-
destination[3] = (byte)((codepoint & 0x3F) | 0x80);
207-
destination = destination.Slice(4);
208-
source = source.Slice(2);
209-
continue;
210218
}
211219

212-
// unpaired high/low surrogate
213-
if (!allowUnpairedSurrogates)
220+
if (dstEnd - dst < 3)
214221
{
215-
c = ReplacementCharacter;
222+
break;
216223
}
224+
*dst++ = (byte)((c >> 12) | 0xE0);
225+
*dst++ = (byte)(((c >> 6) & 0x3F) | 0x80);
226+
*dst++ = (byte)((c & 0x3F) | 0x80);
217227
}
218-
219-
if (destination.Length < 3)
220-
{
221-
break;
222-
}
223-
destination[0] = (byte)((c >> 12) | 0xE0);
224-
destination[1] = (byte)(((c >> 6) & 0x3F) | 0x80);
225-
destination[2] = (byte)((c & 0x3F) | 0x80);
226-
destination = destination.Slice(3);
227-
source = source.Slice(1);
228228
}
229229
}
230230

0 commit comments

Comments
 (0)