@@ -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