2 * UTF8Encoding.cs - Implementation of the "System.Text.UTF8Encoding" class.
4 * Copyright (c) 2001, 2002 Southern Storm Software, Pty Ltd
5 * Copyright (C) 2004 Novell, Inc (http://www.novell.com)
7 * Permission is hereby granted, free of charge, to any person obtaining
8 * a copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 * OTHER DEALINGS IN THE SOFTWARE.
32 [MonoTODO ("Fix serialization compatibility with MS.NET")]
34 [MonoTODO ("EncoderFallback is not handled")]
36 public class UTF8Encoding : Encoding
38 // Magic number used by Windows for UTF-8.
39 internal const int UTF8_CODE_PAGE = 65001;
42 private bool emitIdentifier;
44 private bool throwOnInvalid;
48 public UTF8Encoding () : this (false, false) {}
49 public UTF8Encoding (bool encoderShouldEmitUTF8Identifier)
50 : this (encoderShouldEmitUTF8Identifier, false) {}
52 public UTF8Encoding (bool encoderShouldEmitUTF8Identifier, bool throwOnInvalidBytes)
53 : base (UTF8_CODE_PAGE)
55 emitIdentifier = encoderShouldEmitUTF8Identifier;
57 if (throwOnInvalidBytes)
58 SetFallbackInternal (null, new DecoderExceptionFallback ());
60 SetFallbackInternal (null, new DecoderReplacementFallback (String.Empty));
62 throwOnInvalid = throwOnInvalidBytes;
65 web_name = body_name = header_name = "utf-8";
66 encoding_name = "Unicode (UTF-8)";
67 is_browser_save = true;
68 is_browser_display = true;
69 is_mail_news_display = true;
70 windows_code_page = UnicodeEncoding.UNICODE_CODE_PAGE;
73 // Internal version of "GetByteCount" which can handle a rolling
74 // state between multiple calls to this method.
75 private static int InternalGetByteCount (char[] chars, int index, int count, uint leftOver, bool flush)
77 // Validate the parameters.
79 throw new ArgumentNullException ("chars");
81 if (index < 0 || index > chars.Length) {
82 throw new ArgumentOutOfRangeException ("index", _("ArgRange_Array"));
84 if (count < 0 || count > (chars.Length - index)) {
85 throw new ArgumentOutOfRangeException ("count", _("ArgRange_Array"));
88 // Determine the lengths of all characters.
97 } else if (ch < '\u0800') {
99 } else if (ch >= '\uD800' && ch <= '\uDBFF') {
100 // This is the start of a surrogate pair.
105 } else if (ch >= '\uDC00' && ch <= '\uDFFF') {
106 // We have a surrogate pair.
110 // We have a surrogate start followed by a
111 // regular character. Technically, this is
112 // invalid, but we have to do something.
113 // We write out the surrogate start and then
114 // re-visit the current character again.
122 if (flush && pair != 0) {
123 // Flush the left-over surrogate pair start.
127 // Return the final length to the caller.
131 // Get the number of bytes needed to encode a character buffer.
132 public override int GetByteCount (char[] chars, int index, int count)
134 return InternalGetByteCount (chars, index, count, 0, true);
137 // Convenience wrappers for "GetByteCount".
138 public override int GetByteCount (String s)
140 // Validate the parameters.
142 throw new ArgumentNullException ("s");
145 // Determine the lengths of all characters.
148 int count = s.Length;
155 } else if (ch < '\u0800') {
157 } else if (ch >= '\uD800' && ch <= '\uDBFF' && count > 1) {
158 // This may be the start of a surrogate pair.
159 pair = (uint)(s[index]);
160 if (pair >= (uint)0xDC00 && pair <= (uint)0xDFFF) {
173 // Return the final length to the caller.
177 // Internal version of "GetBytes" which can handle a rolling
178 // state between multiple calls to this method.
179 private static int InternalGetBytes (char[] chars, int charIndex,
180 int charCount, byte[] bytes,
181 int byteIndex, ref uint leftOver,
184 // Validate the parameters.
186 throw new ArgumentNullException ("chars");
189 throw new ArgumentNullException ("bytes");
191 if (charIndex < 0 || charIndex > chars.Length) {
192 throw new ArgumentOutOfRangeException ("charIndex", _("ArgRange_Array"));
194 if (charCount < 0 || charCount > (chars.Length - charIndex)) {
195 throw new ArgumentOutOfRangeException ("charCount", _("ArgRange_Array"));
197 if (byteIndex < 0 || byteIndex > bytes.Length) {
198 throw new ArgumentOutOfRangeException ("byteIndex", _("ArgRange_Array"));
201 // Convert the characters into bytes.
203 int length = bytes.Length;
205 uint left = leftOver;
206 int posn = byteIndex;
207 while (charCount > 0) {
208 // Fetch the next UTF-16 character pair value.
209 ch = chars[charIndex++];
212 if (ch >= '\uD800' && ch <= '\uDBFF') {
213 // This is the start of a surrogate pair.
217 // This is a regular character.
220 } else if (ch >= '\uDC00' && ch <= '\uDFFF') {
221 // We have a surrogate pair.
222 pair = ((left - (uint)0xD800) << 10) +
223 (((uint)ch) - (uint)0xDC00) +
227 // We have a surrogate start followed by a
228 // regular character. Technically, this is
229 // invalid, but we have to do something.
230 // We write out the surrogate start and then
231 // re-visit the current character again.
238 // Encode the character pair value.
239 if (pair < (uint)0x0080) {
240 if (posn >= length) {
241 throw new ArgumentException (_("Arg_InsufficientSpace"), "bytes");
243 bytes[posn++] = (byte)pair;
244 } else if (pair < (uint)0x0800) {
245 if ((posn + 2) > length) {
246 throw new ArgumentException (_("Arg_InsufficientSpace"), "bytes");
248 bytes[posn++] = (byte)(0xC0 | (pair >> 6));
249 bytes[posn++] = (byte)(0x80 | (pair & 0x3F));
250 } else if (pair < (uint)0x10000) {
251 if ((posn + 3) > length) {
252 throw new ArgumentException (_("Arg_InsufficientSpace"), "bytes");
254 bytes[posn++] = (byte)(0xE0 | (pair >> 12));
255 bytes[posn++] = (byte)(0x80 | ((pair >> 6) & 0x3F));
256 bytes[posn++] = (byte)(0x80 | (pair & 0x3F));
258 if ((posn + 4) > length) {
259 throw new ArgumentException (_("Arg_InsufficientSpace"), "bytes");
261 bytes[posn++] = (byte)(0xF0 | (pair >> 18));
262 bytes[posn++] = (byte)(0x80 | ((pair >> 12) & 0x3F));
263 bytes[posn++] = (byte)(0x80 | ((pair >> 6) & 0x3F));
264 bytes[posn++] = (byte)(0x80 | (pair & 0x3F));
267 if (flush && left != 0) {
268 // Flush the left-over surrogate pair start.
269 if ((posn + 3) > length) {
270 throw new ArgumentException (_("Arg_InsufficientSpace"), "bytes");
272 bytes[posn++] = (byte)(0xE0 | (left >> 12));
273 bytes[posn++] = (byte)(0x80 | ((left >> 6) & 0x3F));
274 bytes[posn++] = (byte)(0x80 | (left & 0x3F));
279 // Return the final count to the caller.
280 return posn - byteIndex;
283 // Get the bytes that result from encoding a character buffer.
284 public override int GetBytes (char[] chars, int charIndex, int charCount,
285 byte[] bytes, int byteIndex)
288 return InternalGetBytes (chars, charIndex, charCount, bytes, byteIndex, ref leftOver, true);
291 // Convenience wrappers for "GetBytes".
292 public override int GetBytes (String s, int charIndex, int charCount,
293 byte[] bytes, int byteIndex)
295 // Validate the parameters.
297 throw new ArgumentNullException ("s");
300 throw new ArgumentNullException ("bytes");
302 if (charIndex < 0 || charIndex > s.Length) {
303 throw new ArgumentOutOfRangeException ("charIndex", _("ArgRange_StringIndex"));
305 if (charCount < 0 || charCount > (s.Length - charIndex)) {
306 throw new ArgumentOutOfRangeException ("charCount", _("ArgRange_StringRange"));
308 if (byteIndex < 0 || byteIndex > bytes.Length) {
309 throw new ArgumentOutOfRangeException ("byteIndex", _("ArgRange_Array"));
312 // Convert the characters into bytes.
314 int length = bytes.Length;
316 int posn = byteIndex;
317 while (charCount > 0) {
318 // Fetch the next UTF-16 character pair value.
320 if (ch >= '\uD800' && ch <= '\uDBFF' && charCount > 1) {
321 // This may be the start of a surrogate pair.
322 pair = (uint)(s[charIndex]);
323 if (pair >= (uint)0xDC00 && pair <= (uint)0xDFFF) {
324 pair = (pair - (uint)0xDC00) +
325 ((((uint)ch) - (uint)0xD800) << 10) +
337 // Encode the character pair value.
338 if (pair < (uint)0x0080) {
339 if (posn >= length) {
340 throw new ArgumentException (_("Arg_InsufficientSpace"), "bytes");
342 bytes[posn++] = (byte)pair;
343 } else if (pair < (uint)0x0800) {
344 if ((posn + 2) > length) {
345 throw new ArgumentException (_("Arg_InsufficientSpace"), "bytes");
347 bytes[posn++] = (byte)(0xC0 | (pair >> 6));
348 bytes[posn++] = (byte)(0x80 | (pair & 0x3F));
349 } else if (pair < (uint)0x10000) {
350 if ((posn + 3) > length) {
351 throw new ArgumentException (_("Arg_InsufficientSpace"), "bytes");
353 bytes[posn++] = (byte)(0xE0 | (pair >> 12));
354 bytes[posn++] = (byte)(0x80 | ((pair >> 6) & 0x3F));
355 bytes[posn++] = (byte)(0x80 | (pair & 0x3F));
357 if ((posn + 4) > length) {
358 throw new ArgumentException (_("Arg_InsufficientSpace"), "bytes");
360 bytes[posn++] = (byte)(0xF0 | (pair >> 18));
361 bytes[posn++] = (byte)(0x80 | ((pair >> 12) & 0x3F));
362 bytes[posn++] = (byte)(0x80 | ((pair >> 6) & 0x3F));
363 bytes[posn++] = (byte)(0x80 | (pair & 0x3F));
367 // Return the final count to the caller.
368 return posn - byteIndex;
371 // Internal version of "GetCharCount" which can handle a rolling
372 // state between multiple calls to this method.
374 // Internal version of "GetCharCount" which can handle a rolling
375 // state between multiple calls to this method.
376 private static int InternalGetCharCount (
377 byte[] bytes, int index, int count, uint leftOverBits,
378 uint leftOverCount, DecoderFallbackBuffer fallbackBuffer, bool flush)
380 private static int InternalGetCharCount (
381 byte[] bytes, int index, int count, uint leftOverBits,
382 uint leftOverCount, bool throwOnInvalid, bool flush)
385 // Validate the parameters.
387 throw new ArgumentNullException ("bytes");
389 if (index < 0 || index > bytes.Length) {
390 throw new ArgumentOutOfRangeException ("index", _("ArgRange_Array"));
392 if (count < 0 || count > (bytes.Length - index)) {
393 throw new ArgumentOutOfRangeException ("count", _("ArgRange_Array"));
396 // Determine the number of characters that we have.
399 uint leftBits = leftOverBits;
400 uint leftSoFar = (leftOverCount & (uint)0x0F);
401 uint leftSize = ((leftOverCount >> 4) & (uint)0x0F);
403 ch = (uint)(bytes[index++]);
406 // Process a UTF-8 start character.
407 if (ch < (uint)0x0080) {
408 // Single-byte UTF-8 character.
410 } else if ((ch & (uint)0xE0) == (uint)0xC0) {
411 // Double-byte UTF-8 character.
412 leftBits = (ch & (uint)0x1F);
415 } else if ((ch & (uint)0xF0) == (uint)0xE0) {
416 // Three-byte UTF-8 character.
417 leftBits = (ch & (uint)0x0F);
420 } else if ((ch & (uint)0xF8) == (uint)0xF0) {
421 // Four-byte UTF-8 character.
422 leftBits = (ch & (uint)0x07);
425 } else if ((ch & (uint)0xFC) == (uint)0xF8) {
426 // Five-byte UTF-8 character.
427 leftBits = (ch & (uint)0x03);
430 } else if ((ch & (uint)0xFE) == (uint)0xFC) {
431 // Six-byte UTF-8 character.
432 leftBits = (ch & (uint)0x03);
436 // Invalid UTF-8 start character.
438 length += Fallback (fallbackBuffer, bytes, index - 1);
441 throw new ArgumentException (_("Arg_InvalidUTF8"), "bytes");
445 // Process an extra byte in a multi-byte sequence.
446 if ((ch & (uint)0xC0) == (uint)0x80) {
447 leftBits = ((leftBits << 6) | (ch & (uint)0x3F));
448 if (++leftSoFar >= leftSize) {
449 // We have a complete character now.
450 if (leftBits < (uint)0x10000) {
451 // is it an overlong ?
452 bool overlong = false;
455 overlong = (leftBits <= 0x7F);
458 overlong = (leftBits <= 0x07FF);
461 overlong = (leftBits <= 0xFFFF);
464 overlong = (leftBits <= 0x1FFFFF);
467 overlong = (leftBits <= 0x03FFFFFF);
472 length += Fallback (fallbackBuffer, bytes, index - 1);
475 throw new ArgumentException (_("Overlong"), leftBits.ToString ());
480 } else if (leftBits < (uint)0x110000) {
484 length += Fallback (fallbackBuffer, bytes, index - 1);
487 throw new ArgumentException (_("Arg_InvalidUTF8"), "bytes");
493 // Invalid UTF-8 sequence: clear and restart.
495 length += Fallback (fallbackBuffer, bytes, index - 1);
498 throw new ArgumentException (_("Arg_InvalidUTF8"), "bytes");
506 if (flush && leftSize != 0) {
507 // We had left-over bytes that didn't make up
508 // a complete UTF-8 character sequence.
510 length += Fallback (fallbackBuffer, bytes, index - 1);
513 throw new ArgumentException (_("Arg_InvalidUTF8"), "bytes");
517 // Return the final length to the caller.
522 // for GetCharCount()
523 static int Fallback (DecoderFallbackBuffer buffer, byte [] bytes, int index)
525 buffer.Fallback (bytes, index - 1);
526 return buffer.Remaining;
530 static void Fallback (DecoderFallbackBuffer buffer, byte [] bytes, int byteIndex,
531 char [] chars, ref int charIndex)
533 buffer.Fallback (bytes, byteIndex - 1);
534 while (buffer.Remaining > 0)
535 chars [charIndex++] = buffer.GetNextChar ();
539 // Get the number of characters needed to decode a byte buffer.
540 public override int GetCharCount (byte[] bytes, int index, int count)
543 return InternalGetCharCount (bytes, index, count, 0, 0, DecoderFallback.CreateFallbackBuffer (), true);
545 return InternalGetCharCount (bytes, index, count, 0, 0, throwOnInvalid, true);
549 // Get the characters that result from decoding a byte buffer.
551 private static int InternalGetChars (
552 byte[] bytes, int byteIndex, int byteCount, char[] chars,
553 int charIndex, ref uint leftOverBits, ref uint leftOverCount,
554 DecoderFallbackBuffer fallbackBuffer, bool flush)
556 private static int InternalGetChars (
557 byte[] bytes, int byteIndex, int byteCount, char[] chars,
558 int charIndex, ref uint leftOverBits, ref uint leftOverCount,
559 bool throwOnInvalid, bool flush)
562 // Validate the parameters.
564 throw new ArgumentNullException ("bytes");
567 throw new ArgumentNullException ("chars");
569 if (byteIndex < 0 || byteIndex > bytes.Length) {
570 throw new ArgumentOutOfRangeException ("byteIndex", _("ArgRange_Array"));
572 if (byteCount < 0 || byteCount > (bytes.Length - byteIndex)) {
573 throw new ArgumentOutOfRangeException ("byteCount", _("ArgRange_Array"));
575 if (charIndex < 0 || charIndex > chars.Length) {
576 throw new ArgumentOutOfRangeException ("charIndex", _("ArgRange_Array"));
579 if (charIndex == chars.Length)
582 // Convert the bytes into the output buffer.
584 int length = chars.Length;
585 int posn = charIndex;
586 uint leftBits = leftOverBits;
587 uint leftSoFar = (leftOverCount & (uint)0x0F);
588 uint leftSize = ((leftOverCount >> 4) & (uint)0x0F);
589 while (byteCount > 0) {
590 // Fetch the next character from the byte buffer.
591 ch = (uint)(bytes[byteIndex++]);
594 // Process a UTF-8 start character.
595 if (ch < (uint)0x0080) {
596 // Single-byte UTF-8 character.
597 if (posn >= length) {
598 throw new ArgumentException (_("Arg_InsufficientSpace"), "chars");
600 chars[posn++] = (char)ch;
601 } else if ((ch & (uint)0xE0) == (uint)0xC0) {
602 // Double-byte UTF-8 character.
603 leftBits = (ch & (uint)0x1F);
606 } else if ((ch & (uint)0xF0) == (uint)0xE0) {
607 // Three-byte UTF-8 character.
608 leftBits = (ch & (uint)0x0F);
611 } else if ((ch & (uint)0xF8) == (uint)0xF0) {
612 // Four-byte UTF-8 character.
613 leftBits = (ch & (uint)0x07);
616 } else if ((ch & (uint)0xFC) == (uint)0xF8) {
617 // Five-byte UTF-8 character.
618 leftBits = (ch & (uint)0x03);
621 } else if ((ch & (uint)0xFE) == (uint)0xFC) {
622 // Six-byte UTF-8 character.
623 leftBits = (ch & (uint)0x03);
627 // Invalid UTF-8 start character.
629 Fallback (fallbackBuffer, bytes, byteIndex, chars, ref posn);
632 throw new ArgumentException (_("Arg_InvalidUTF8"), "bytes");
636 // Process an extra byte in a multi-byte sequence.
637 if ((ch & (uint)0xC0) == (uint)0x80) {
638 leftBits = ((leftBits << 6) | (ch & (uint)0x3F));
639 if (++leftSoFar >= leftSize) {
640 // We have a complete character now.
641 if (leftBits < (uint)0x10000) {
642 // is it an overlong ?
643 bool overlong = false;
646 overlong = (leftBits <= 0x7F);
649 overlong = (leftBits <= 0x07FF);
652 overlong = (leftBits <= 0xFFFF);
655 overlong = (leftBits <= 0x1FFFFF);
658 overlong = (leftBits <= 0x03FFFFFF);
663 Fallback (fallbackBuffer, bytes, byteIndex, chars, ref posn);
666 throw new ArgumentException (_("Overlong"), leftBits.ToString ());
670 if (posn >= length) {
671 throw new ArgumentException
672 (_("Arg_InsufficientSpace"), "chars");
674 chars[posn++] = (char)leftBits;
676 } else if (leftBits < (uint)0x110000) {
677 if ((posn + 2) > length) {
678 throw new ArgumentException
679 (_("Arg_InsufficientSpace"), "chars");
681 leftBits -= (uint)0x10000;
682 chars[posn++] = (char)((leftBits >> 10) +
685 (char)((leftBits & (uint)0x3FF) + (uint)0xDC00);
688 Fallback (fallbackBuffer, bytes, byteIndex, chars, ref posn);
691 throw new ArgumentException (_("Arg_InvalidUTF8"), "bytes");
697 // Invalid UTF-8 sequence: clear and restart.
699 Fallback (fallbackBuffer, bytes, byteIndex, chars, ref posn);
702 throw new ArgumentException (_("Arg_InvalidUTF8"), "bytes");
710 if (flush && leftSize != 0) {
711 // We had left-over bytes that didn't make up
712 // a complete UTF-8 character sequence.
714 Fallback (fallbackBuffer, bytes, byteIndex, chars, ref posn);
717 throw new ArgumentException (_("Arg_InvalidUTF8"), "bytes");
720 leftOverBits = leftBits;
721 leftOverCount = (leftSoFar | (leftSize << 4));
723 // Return the final length to the caller.
724 return posn - charIndex;
727 // Get the characters that result from decoding a byte buffer.
728 public override int GetChars (byte[] bytes, int byteIndex, int byteCount,
729 char[] chars, int charIndex)
731 uint leftOverBits = 0;
732 uint leftOverCount = 0;
734 return InternalGetChars (bytes, byteIndex, byteCount, chars,
735 charIndex, ref leftOverBits, ref leftOverCount, DecoderFallback.CreateFallbackBuffer (), true);
737 return InternalGetChars (bytes, byteIndex, byteCount, chars,
738 charIndex, ref leftOverBits, ref leftOverCount, throwOnInvalid, true);
742 // Get the maximum number of bytes needed to encode a
743 // specified number of characters.
744 public override int GetMaxByteCount (int charCount)
747 throw new ArgumentOutOfRangeException ("charCount", _("ArgRange_NonNegative"));
749 return charCount * 4;
752 // Get the maximum number of characters needed to decode a
753 // specified number of bytes.
754 public override int GetMaxCharCount (int byteCount)
757 throw new ArgumentOutOfRangeException ("byteCount", _("ArgRange_NonNegative"));
762 // Get a UTF8-specific decoder that is attached to this instance.
763 public override Decoder GetDecoder ()
766 return new UTF8Decoder (DecoderFallback);
768 return new UTF8Decoder (throwOnInvalid);
772 // Get a UTF8-specific encoder that is attached to this instance.
773 public override Encoder GetEncoder ()
775 return new UTF8Encoder (emitIdentifier);
778 // Get the UTF8 preamble.
779 public override byte[] GetPreamble ()
781 if (emitIdentifier) {
782 byte[] pre = new byte [3];
792 // Determine if this object is equal to another.
793 public override bool Equals (Object value)
795 UTF8Encoding enc = (value as UTF8Encoding);
798 return (codePage == enc.codePage &&
799 emitIdentifier == enc.emitIdentifier &&
800 DecoderFallback == enc.DecoderFallback &&
801 EncoderFallback == enc.EncoderFallback);
803 return (codePage == enc.codePage &&
804 emitIdentifier == enc.emitIdentifier &&
805 throwOnInvalid == enc.throwOnInvalid);
812 // Get the hash code for this object.
813 public override int GetHashCode ()
815 return base.GetHashCode ();
818 public override byte [] GetBytes (String s)
821 throw new ArgumentNullException ("s");
823 int length = GetByteCount (s);
824 byte [] bytes = new byte [length];
825 GetBytes (s, 0, s.Length, bytes, 0);
829 // UTF-8 decoder implementation.
831 private class UTF8Decoder : Decoder
834 private bool throwOnInvalid;
836 private uint leftOverBits;
837 private uint leftOverCount;
841 public UTF8Decoder (DecoderFallback fallback)
843 public UTF8Decoder (bool throwOnInvalid)
849 this.throwOnInvalid = throwOnInvalid;
855 // Override inherited methods.
856 public override int GetCharCount (byte[] bytes, int index, int count)
859 return InternalGetCharCount (bytes, index, count,
860 leftOverBits, leftOverCount, FallbackBuffer, false);
862 return InternalGetCharCount (bytes, index, count,
863 leftOverBits, leftOverCount, throwOnInvalid, false);
866 public override int GetChars (byte[] bytes, int byteIndex,
867 int byteCount, char[] chars, int charIndex)
870 return InternalGetChars (bytes, byteIndex, byteCount,
871 chars, charIndex, ref leftOverBits, ref leftOverCount, FallbackBuffer, false);
873 return InternalGetChars (bytes, byteIndex, byteCount,
874 chars, charIndex, ref leftOverBits, ref leftOverCount, throwOnInvalid, false);
878 } // class UTF8Decoder
880 // UTF-8 encoder implementation.
882 private class UTF8Encoder : Encoder
884 private bool emitIdentifier;
885 private uint leftOver;
888 public UTF8Encoder (bool emitIdentifier)
890 this.emitIdentifier = emitIdentifier;
894 // Override inherited methods.
895 public override int GetByteCount (char[] chars, int index,
896 int count, bool flush)
898 return InternalGetByteCount (chars, index, count, leftOver, flush);
900 public override int GetBytes (char[] chars, int charIndex,
901 int charCount, byte[] bytes, int byteCount, bool flush)
904 result = InternalGetBytes (chars, charIndex, charCount, bytes, byteCount, ref leftOver, flush);
905 emitIdentifier = false;
909 } // class UTF8Encoder
911 }; // class UTF8Encoding
913 }; // namespace System.Text