private void EncodeCore(ref Writer writer, char *input, uint charsRemaining) { while (charsRemaining != 0) { int nextScalar = UnicodeHelpers.GetScalarValueFromUtf16(input, endOfString: (charsRemaining == 1)); if (UnicodeHelpers.IsSupplementaryCodePoint(nextScalar)) { // Supplementary characters should always be encoded numerically. WriteEncodedScalar(ref writer, (uint)nextScalar); // We consume two UTF-16 characters for a single supplementary character. input += 2; charsRemaining -= 2; } else { // Otherwise, this was a BMP character. input++; charsRemaining--; char c = (char)nextScalar; if (IsCharacterAllowed(c)) { writer.Write(c); } else { WriteEncodedScalar(ref writer, (uint)nextScalar); } } } }
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); } }
private static unsafe void EncodeCore(this TextEncoder encoder, char *value, int charCount, TextWriter output) { int bufferLength = encoder.MaxOutputCharsPerInputChar; 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 < charCount; secondCharIndex++) { if (!wasSurrogatePair) { firstChar = secondChar; } else { firstChar = value[secondCharIndex - 1]; } secondChar = value[secondCharIndex]; if (!encoder.Encodes(firstChar)) { wasSurrogatePair = false; output.Write(firstChar); } else { int nextScalar = UnicodeHelpers.GetScalarValueFromUtf16(firstChar, secondChar, out wasSurrogatePair); if (!encoder.TryEncodeUnicodeScalar(nextScalar, buffer, bufferLength, out charsWritten)) { throw new ArgumentException("Argument encoder does not implement MaxOutputCharsPerInputChar correctly."); } output.Write(buffer, charsWritten); if (wasSurrogatePair) { secondCharIndex++; } } } if (!wasSurrogatePair) { firstChar = value[charCount - 1]; int nextScalar = UnicodeHelpers.GetScalarValueFromUtf16(firstChar, null, out wasSurrogatePair); if (!encoder.TryEncodeUnicodeScalar(nextScalar, buffer, bufferLength, out charsWritten)) { throw new ArgumentException("Argument encoder does not implement MaxOutputCharsPerInputChar correctly."); } output.Write(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) { Debug.Assert(firstCharacterToEncode <= valueLength); Buffer.MemoryCopy(source: value, destination: buffer, destinationSizeInBytes: sizeof(char) * bufferLength, sourceBytesToCopy: sizeof(char) * firstCharacterToEncode); 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. int secondCharIndex; for (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 (secondCharIndex == valueLength) { 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); }
private unsafe OperationStatus EncodeIntoBuffer( char *buffer, int bufferLength, char *value, int valueLength, out int charsConsumed, out int charsWritten, int firstCharacterToEncode, bool isFinalBlock = true) { Debug.Assert(value != null); Debug.Assert(firstCharacterToEncode >= 0); char *originalBuffer = buffer; charsWritten = 0; if (firstCharacterToEncode > 0) { Debug.Assert(firstCharacterToEncode <= valueLength); Buffer.MemoryCopy(source: value, destination: buffer, destinationSizeInBytes: sizeof(char) * bufferLength, sourceBytesToCopy: sizeof(char) * firstCharacterToEncode); charsWritten += firstCharacterToEncode; bufferLength -= firstCharacterToEncode; buffer += firstCharacterToEncode; } int valueIndex = firstCharacterToEncode; char firstChar = value[valueIndex]; char secondChar = firstChar; bool wasSurrogatePair = false; // this loop processes character pairs (in case they are surrogates). // there is an if block below to process single last character. int secondCharIndex; for (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--; charsWritten++; } else { int nextScalar = UnicodeHelpers.GetScalarValueFromUtf16(firstChar, secondChar, out wasSurrogatePair, out bool _); if (!TryEncodeUnicodeScalar(nextScalar, buffer, bufferLength, out int charsWrittenThisTime)) { charsConsumed = (int)(originalBuffer - buffer); return(OperationStatus.DestinationTooSmall); } if (wasSurrogatePair) { secondCharIndex++; } buffer += charsWrittenThisTime; bufferLength -= charsWrittenThisTime; charsWritten += charsWrittenThisTime; } } if (secondCharIndex == valueLength) { firstChar = value[valueLength - 1]; int nextScalar = UnicodeHelpers.GetScalarValueFromUtf16(firstChar, null, out wasSurrogatePair, out bool needMoreData); if (!isFinalBlock && needMoreData) { Debug.Assert(wasSurrogatePair == false); charsConsumed = (int)(buffer - originalBuffer); return(OperationStatus.NeedMoreData); } if (!TryEncodeUnicodeScalar(nextScalar, buffer, bufferLength, out int charsWrittenThisTime)) { charsConsumed = (int)(buffer - originalBuffer); return(OperationStatus.DestinationTooSmall); } buffer += charsWrittenThisTime; bufferLength -= charsWrittenThisTime; charsWritten += charsWrittenThisTime; } charsConsumed = valueLength; return(OperationStatus.Done); }
public static string Encode(this TextEncoder encoder, string value) { if (value == null) { return(value); } unsafe { fixed(char *valuePointer = value) { int firstCharacterToEncode = encoder.FindFirstCharacterToEncode(valuePointer, value.Length); if (firstCharacterToEncode == -1) { return(value); } int bufferSize = encoder.MaxOutputCharsPerInputChar * value.Length; char *wholebuffer = stackalloc char[bufferSize]; char *buffer = wholebuffer; int totalWritten = 0; if (firstCharacterToEncode > 0) { int bytesToCopy = firstCharacterToEncode + firstCharacterToEncode; Buffer.MemoryCopy(valuePointer, buffer, bytesToCopy, bytesToCopy); totalWritten += firstCharacterToEncode; bufferSize -= 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 < value.Length; secondCharIndex++) { if (!wasSurrogatePair) { firstChar = secondChar; } else { firstChar = value[secondCharIndex - 1]; } secondChar = value[secondCharIndex]; if (!encoder.Encodes(firstChar)) { wasSurrogatePair = false; *buffer = firstChar; buffer++; bufferSize--; totalWritten++; } else { int nextScalar = UnicodeHelpers.GetScalarValueFromUtf16(firstChar, secondChar, out wasSurrogatePair); if (!encoder.TryEncodeUnicodeScalar(nextScalar, buffer, bufferSize, out charsWritten)) { throw new ArgumentException("Argument encoder does not implement MaxOutputCharsPerInputChar correctly."); } buffer += charsWritten; bufferSize -= charsWritten; totalWritten += charsWritten; if (wasSurrogatePair) { secondCharIndex++; } } } if (!wasSurrogatePair) { firstChar = value[value.Length - 1]; int nextScalar = UnicodeHelpers.GetScalarValueFromUtf16(firstChar, null, out wasSurrogatePair); if (!encoder.TryEncodeUnicodeScalar(nextScalar, buffer, bufferSize, out charsWritten)) { throw new ArgumentException("Argument encoder does not implement MaxOutputCharsPerInputChar correctly."); } buffer += charsWritten; bufferSize -= charsWritten; totalWritten += charsWritten; } var result = new String(wholebuffer, 0, totalWritten); return(result); } } }