private unsafe void EncodeCore(TextWriter output, char *value, int valueLength) { Debug.Assert(value != null & output != null); Debug.Assert(valueLength >= 0); int bufferLength = MaxOutputCharactersPerInputCharacter; char *buffer = stackalloc char[bufferLength]; char firstChar = *value; char secondChar = firstChar; bool wasSurrogatePair = false; int charsWritten; // this loop processes character pairs (in case they are surrogates). // there is an if block below to process single last character. for (int secondCharIndex = 1; secondCharIndex < valueLength; secondCharIndex++) { if (!wasSurrogatePair) { firstChar = secondChar; } else { firstChar = value[secondCharIndex - 1]; } secondChar = value[secondCharIndex]; if (!WillEncode(firstChar)) { wasSurrogatePair = false; output.Write(firstChar); } else { int nextScalar = UnicodeHelpers.GetScalarValueFromUtf16(firstChar, secondChar, out wasSurrogatePair); if (!TryEncodeUnicodeScalar(nextScalar, buffer, bufferLength, out charsWritten)) { throw new ArgumentException("Argument encoder does not implement MaxOutputCharsPerInputChar correctly."); } Write(output, buffer, charsWritten); if (wasSurrogatePair) { secondCharIndex++; } } } if (!wasSurrogatePair) { firstChar = value[valueLength - 1]; int nextScalar = UnicodeHelpers.GetScalarValueFromUtf16(firstChar, null, out wasSurrogatePair); if (!TryEncodeUnicodeScalar(nextScalar, buffer, bufferLength, out charsWritten)) { throw new ArgumentException("Argument encoder does not implement MaxOutputCharsPerInputChar correctly."); } Write(output, buffer, charsWritten); } }
// NOTE: The order of the parameters to this method is a work around for https://github.com/dotnet/corefx/issues/4455 // and the underlying Mono bug: https://bugzilla.xamarin.com/show_bug.cgi?id=36052. // If changing the signature of this method, ensure this issue isn't regressing on Mono. private unsafe int EncodeIntoBuffer(char *buffer, int bufferLength, char *value, int valueLength, int firstCharacterToEncode) { int totalWritten = 0; if (firstCharacterToEncode > 0) { int bytesToCopy = firstCharacterToEncode + firstCharacterToEncode; //commont by jyq in 2018.7.6 //BufferInternal.MemoryCopy(value, buffer, bytesToCopy, bytesToCopy); totalWritten += firstCharacterToEncode; bufferLength -= firstCharacterToEncode; buffer += firstCharacterToEncode; } int valueIndex = firstCharacterToEncode; char firstChar = value[valueIndex]; char secondChar = firstChar; bool wasSurrogatePair = false; int charsWritten; // this loop processes character pairs (in case they are surrogates). // there is an if block below to process single last character. for (int secondCharIndex = valueIndex + 1; secondCharIndex < valueLength; secondCharIndex++) { if (!wasSurrogatePair) { firstChar = secondChar; } else { firstChar = value[secondCharIndex - 1]; } secondChar = value[secondCharIndex]; if (!WillEncode(firstChar)) { wasSurrogatePair = false; *buffer = firstChar; buffer++; bufferLength--; totalWritten++; } else { int nextScalar = UnicodeHelpers.GetScalarValueFromUtf16(firstChar, secondChar, out wasSurrogatePair); if (!TryEncodeUnicodeScalar(nextScalar, buffer, bufferLength, out charsWritten)) { throw new ArgumentException("Argument encoder does not implement MaxOutputCharsPerInputChar correctly."); } buffer += charsWritten; bufferLength -= charsWritten; totalWritten += charsWritten; if (wasSurrogatePair) { secondCharIndex++; } } } if (!wasSurrogatePair) { firstChar = value[valueLength - 1]; int nextScalar = UnicodeHelpers.GetScalarValueFromUtf16(firstChar, null, out wasSurrogatePair); if (!TryEncodeUnicodeScalar(nextScalar, buffer, bufferLength, out charsWritten)) { throw new ArgumentException("Argument encoder does not implement MaxOutputCharsPerInputChar correctly."); } buffer += charsWritten; bufferLength -= charsWritten; totalWritten += charsWritten; } return(totalWritten); }