public static void Encode(this TextEncoder encoder, TextWriter output, char[] value, int startIndex, int characterCount) { if (encoder == null) { throw new ArgumentNullException("encoder"); } if (value == null) { throw new ArgumentNullException("value"); } if (output == null) { throw new ArgumentNullException("output"); } ValidateRanges(startIndex, characterCount, actualInputLength: value.Length); unsafe { fixed(char *valuePointer = value) { char *substring = valuePointer + startIndex; int firstIndexToEncode = encoder.FindFirstCharacterToEncode(substring, characterCount); if (firstIndexToEncode == -1) // nothing to encode; { if (startIndex == 0 && characterCount == value.Length) // write whole string { output.Write(value); return; } for (int i = 0; i < characterCount; i++) // write substring { output.Write(*substring); substring++; } return; } // write prefix, then encode for (int i = 0; i < firstIndexToEncode; i++) { output.Write(*substring); substring++; } EncodeCore(encoder, output, substring, characterCount - firstIndexToEncode); } } }
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); } } }