Encoding.cs 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815
  1. /*
  2. * Encoding.cs - Implementation of the "System.Text.Encoding" class.
  3. *
  4. * Copyright (c) 2001, 2002 Southern Storm Software, Pty Ltd
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining
  7. * a copy of this software and associated documentation files (the "Software"),
  8. * to deal in the Software without restriction, including without limitation
  9. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  10. * and/or sell copies of the Software, and to permit persons to whom the
  11. * Software is furnished to do so, subject to the following conditions:
  12. *
  13. * The above copyright notice and this permission notice shall be included
  14. * in all copies or substantial portions of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  17. * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  20. * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  21. * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  22. * OTHER DEALINGS IN THE SOFTWARE.
  23. */
  24. namespace System.Text
  25. {
  26. using System;
  27. using System.Reflection;
  28. using System.Globalization;
  29. using System.Security;
  30. public abstract class Encoding
  31. {
  32. // Code page used by this encoding.
  33. internal int codePage;
  34. // Constructor.
  35. protected Encoding()
  36. {
  37. codePage = 0;
  38. }
  39. #if ECMA_COMPAT
  40. protected internal
  41. #else
  42. protected
  43. #endif
  44. Encoding(int codePage)
  45. {
  46. this.codePage = codePage;
  47. }
  48. // until we change the callers:
  49. internal static string _ (string arg) {
  50. return arg;
  51. }
  52. // Convert between two encodings.
  53. public static byte[] Convert(Encoding srcEncoding, Encoding dstEncoding,
  54. byte[] bytes)
  55. {
  56. if(srcEncoding == null)
  57. {
  58. throw new ArgumentNullException("srcEncoding");
  59. }
  60. if(dstEncoding == null)
  61. {
  62. throw new ArgumentNullException("dstEncoding");
  63. }
  64. if(bytes == null)
  65. {
  66. throw new ArgumentNullException("bytes");
  67. }
  68. return dstEncoding.GetBytes(srcEncoding.GetChars
  69. (bytes, 0, bytes.Length));
  70. }
  71. public static byte[] Convert(Encoding srcEncoding, Encoding dstEncoding,
  72. byte[] bytes, int index, int count)
  73. {
  74. if(srcEncoding == null)
  75. {
  76. throw new ArgumentNullException("srcEncoding");
  77. }
  78. if(dstEncoding == null)
  79. {
  80. throw new ArgumentNullException("dstEncoding");
  81. }
  82. if(bytes == null)
  83. {
  84. throw new ArgumentNullException("bytes");
  85. }
  86. if(index < 0 || index > bytes.Length)
  87. {
  88. throw new ArgumentOutOfRangeException
  89. ("index", _("ArgRange_Array"));
  90. }
  91. if(count < 0 || (bytes.Length - index) < count)
  92. {
  93. throw new ArgumentOutOfRangeException
  94. ("count", _("ArgRange_Array"));
  95. }
  96. return dstEncoding.GetBytes(srcEncoding.GetChars
  97. (bytes, index, count));
  98. }
  99. // Determine if two Encoding objects are equal.
  100. public override bool Equals(Object obj)
  101. {
  102. Encoding enc = (obj as Encoding);
  103. if(enc != null)
  104. {
  105. return (codePage == enc.codePage);
  106. }
  107. else
  108. {
  109. return false;
  110. }
  111. }
  112. // Get the number of characters needed to encode a character buffer.
  113. public abstract int GetByteCount(char[] chars, int index, int count);
  114. // Convenience wrappers for "GetByteCount".
  115. public virtual int GetByteCount(String s)
  116. {
  117. if(s != null)
  118. {
  119. char[] chars = s.ToCharArray();
  120. return GetByteCount(chars, 0, chars.Length);
  121. }
  122. else
  123. {
  124. throw new ArgumentNullException("s");
  125. }
  126. }
  127. public virtual int GetByteCount(char[] chars)
  128. {
  129. if(chars != null)
  130. {
  131. return GetByteCount(chars, 0, chars.Length);
  132. }
  133. else
  134. {
  135. throw new ArgumentNullException("chars");
  136. }
  137. }
  138. // Get the bytes that result from encoding a character buffer.
  139. public abstract int GetBytes(char[] chars, int charIndex, int charCount,
  140. byte[] bytes, int byteIndex);
  141. // Convenience wrappers for "GetBytes".
  142. public virtual int GetBytes(String s, int charIndex, int charCount,
  143. byte[] bytes, int byteIndex)
  144. {
  145. if(s == null)
  146. {
  147. throw new ArgumentNullException("s");
  148. }
  149. return GetBytes(s.ToCharArray(), charIndex, charCount,
  150. bytes, byteIndex);
  151. }
  152. public virtual byte[] GetBytes(String s)
  153. {
  154. if(s == null)
  155. {
  156. throw new ArgumentNullException("s");
  157. }
  158. char[] chars = s.ToCharArray();
  159. int numBytes = GetByteCount(chars, 0, chars.Length);
  160. byte[] bytes = new byte [numBytes];
  161. GetBytes(chars, 0, chars.Length, bytes, 0);
  162. return bytes;
  163. }
  164. public virtual byte[] GetBytes(char[] chars, int index, int count)
  165. {
  166. int numBytes = GetByteCount(chars, index, count);
  167. byte[] bytes = new byte [numBytes];
  168. GetBytes(chars, index, count, bytes, 0);
  169. return bytes;
  170. }
  171. public virtual byte[] GetBytes(char[] chars)
  172. {
  173. int numBytes = GetByteCount(chars, 0, chars.Length);
  174. byte[] bytes = new byte [numBytes];
  175. GetBytes(chars, 0, chars.Length, bytes, 0);
  176. return bytes;
  177. }
  178. // Get the number of characters needed to decode a byte buffer.
  179. public abstract int GetCharCount(byte[] bytes, int index, int count);
  180. // Convenience wrappers for "GetCharCount".
  181. public virtual int GetCharCount(byte[] bytes)
  182. {
  183. if(bytes == null)
  184. {
  185. throw new ArgumentNullException("bytes");
  186. }
  187. return GetCharCount(bytes, 0, bytes.Length);
  188. }
  189. // Get the characters that result from decoding a byte buffer.
  190. public abstract int GetChars(byte[] bytes, int byteIndex, int byteCount,
  191. char[] chars, int charIndex);
  192. // Convenience wrappers for "GetChars".
  193. public virtual char[] GetChars(byte[] bytes, int index, int count)
  194. {
  195. int numChars = GetCharCount(bytes, index, count);
  196. char[] chars = new char [numChars];
  197. GetChars(bytes, index, count, chars, 0);
  198. return chars;
  199. }
  200. public virtual char[] GetChars(byte[] bytes)
  201. {
  202. if(bytes == null)
  203. {
  204. throw new ArgumentNullException("bytes");
  205. }
  206. int numChars = GetCharCount(bytes, 0, bytes.Length);
  207. char[] chars = new char [numChars];
  208. GetChars(bytes, 0, bytes.Length, chars, 0);
  209. return chars;
  210. }
  211. // Get a decoder that forwards requests to this object.
  212. public virtual Decoder GetDecoder()
  213. {
  214. return new ForwardingDecoder(this);
  215. }
  216. // Get an encoder that forwards requests to this object.
  217. public virtual Encoder GetEncoder()
  218. {
  219. return new ForwardingEncoder(this);
  220. }
  221. // Loaded copy of the "I18N" assembly. We need to move
  222. // this into a class in "System.Private" eventually.
  223. private static Assembly i18nAssembly;
  224. private static bool i18nDisabled;
  225. // Invoke a specific method on the "I18N" manager object.
  226. // Returns NULL if the method failed.
  227. private static Object InvokeI18N(String name, params Object[] args)
  228. {
  229. lock(typeof(Encoding))
  230. {
  231. // Bail out if we previously detected that there
  232. // is insufficent engine support for I18N handling.
  233. if(i18nDisabled)
  234. {
  235. return null;
  236. }
  237. // Find or load the "I18N" assembly.
  238. if(i18nAssembly == null)
  239. {
  240. try
  241. {
  242. try
  243. {
  244. i18nAssembly = Assembly.Load("I18N");
  245. }
  246. catch(NotImplementedException)
  247. {
  248. // Assembly loading unsupported by the engine.
  249. i18nDisabled = true;
  250. return null;
  251. }
  252. if(i18nAssembly == null)
  253. {
  254. return null;
  255. }
  256. }
  257. catch(SystemException)
  258. {
  259. return null;
  260. }
  261. }
  262. // Find the "I18N.Common.Manager" class.
  263. Type managerClass;
  264. try
  265. {
  266. managerClass =
  267. i18nAssembly.GetType("I18N.Common.Manager");
  268. }
  269. catch(NotImplementedException)
  270. {
  271. // "GetType" is not supported by the engine.
  272. i18nDisabled = true;
  273. return null;
  274. }
  275. if(managerClass == null)
  276. {
  277. return null;
  278. }
  279. // Get the value of the "PrimaryManager" property.
  280. Object manager;
  281. try
  282. {
  283. manager = managerClass.InvokeMember
  284. ("PrimaryManager",
  285. BindingFlags.GetProperty |
  286. BindingFlags.Static |
  287. BindingFlags.Public,
  288. null, null, null, null, null, null);
  289. if(manager == null)
  290. {
  291. return null;
  292. }
  293. }
  294. catch(MissingMethodException)
  295. {
  296. return null;
  297. }
  298. catch(SecurityException)
  299. {
  300. return null;
  301. }
  302. catch(NotImplementedException)
  303. {
  304. // "InvokeMember" is not supported by the engine.
  305. i18nDisabled = true;
  306. return null;
  307. }
  308. // Invoke the requested method on the manager.
  309. try
  310. {
  311. return managerClass.InvokeMember
  312. (name,
  313. BindingFlags.InvokeMethod |
  314. BindingFlags.Instance |
  315. BindingFlags.Public,
  316. null, manager, args, null, null, null);
  317. }
  318. catch(MissingMethodException)
  319. {
  320. return null;
  321. }
  322. catch(SecurityException)
  323. {
  324. return null;
  325. }
  326. }
  327. }
  328. // Get an encoder for a specific code page.
  329. #if ECMA_COMPAT
  330. private
  331. #else
  332. public
  333. #endif
  334. static Encoding GetEncoding(int codePage)
  335. {
  336. // Check for the builtin code pages first.
  337. switch(codePage)
  338. {
  339. case 0: return Default;
  340. case ASCIIEncoding.ASCII_CODE_PAGE:
  341. return ASCII;
  342. case UTF7Encoding.UTF7_CODE_PAGE:
  343. return UTF7;
  344. case UTF8Encoding.UTF8_CODE_PAGE:
  345. return UTF8;
  346. case UnicodeEncoding.UNICODE_CODE_PAGE:
  347. return Unicode;
  348. case UnicodeEncoding.BIG_UNICODE_CODE_PAGE:
  349. return BigEndianUnicode;
  350. case Latin1Encoding.ISOLATIN_CODE_PAGE:
  351. return ISOLatin1;
  352. default: break;
  353. }
  354. // Try to obtain a code page handler from the I18N handler.
  355. Encoding enc = (Encoding)(InvokeI18N("GetEncoding", codePage));
  356. if(enc != null)
  357. {
  358. return enc;
  359. }
  360. #if false
  361. // Build a code page class name.
  362. String cpName = "System.Text.CP" + codePage.ToString();
  363. // Look for a code page converter in this assembly.
  364. Assembly assembly = Assembly.GetExecutingAssembly();
  365. Type type = assembly.GetType(cpName);
  366. if(type != null)
  367. {
  368. return (Encoding)(Activator.CreateInstance(type));
  369. }
  370. // Look in any assembly, in case the application
  371. // has provided its own code page handler.
  372. type = Type.GetType(cpName);
  373. if(type != null)
  374. {
  375. return (Encoding)(Activator.CreateInstance(type));
  376. }
  377. #endif
  378. // We have no idea how to handle this code page.
  379. throw new NotSupportedException
  380. (String.Format
  381. (_("NotSupp_CodePage"), codePage.ToString()));
  382. }
  383. #if !ECMA_COMPAT
  384. // Table of builtin web encoding names and the corresponding code pages.
  385. private static readonly String[] encodingNames =
  386. {"us-ascii", "utf-7", "utf-8", "utf-16",
  387. "unicodeFFFE", "iso-8859-1"};
  388. private static readonly int[] encodingCodePages =
  389. {ASCIIEncoding.ASCII_CODE_PAGE,
  390. UTF7Encoding.UTF7_CODE_PAGE,
  391. UTF8Encoding.UTF8_CODE_PAGE,
  392. UnicodeEncoding.UNICODE_CODE_PAGE,
  393. UnicodeEncoding.BIG_UNICODE_CODE_PAGE,
  394. Latin1Encoding.ISOLATIN_CODE_PAGE};
  395. // Get an encoding object for a specific web encoding name.
  396. public static Encoding GetEncoding(String name)
  397. {
  398. // Validate the parameters.
  399. if(name == null)
  400. {
  401. throw new ArgumentNullException("name");
  402. }
  403. // Search the table for a name match.
  404. int posn;
  405. for(posn = 0; posn < encodingNames.Length; ++posn)
  406. {
  407. if(String.Compare(name, encodingNames[posn], true,
  408. CultureInfo.InvariantCulture) == 0)
  409. {
  410. return GetEncoding(encodingCodePages[posn]);
  411. }
  412. }
  413. // Try to obtain a web encoding handler from the I18N handler.
  414. Encoding enc = (Encoding)(InvokeI18N("GetEncoding", name));
  415. if(enc != null)
  416. {
  417. return enc;
  418. }
  419. #if false
  420. // Build a web encoding class name.
  421. String encName = "System.Text.ENC" +
  422. name.ToLower(CultureInfo.InvariantCulture)
  423. .Replace('-', '_');
  424. // Look for a code page converter in this assembly.
  425. Assembly assembly = Assembly.GetExecutingAssembly();
  426. Type type = assembly.GetType(encName);
  427. if(type != null)
  428. {
  429. return (Encoding)(Activator.CreateInstance(type));
  430. }
  431. // Look in any assembly, in case the application
  432. // has provided its own code page handler.
  433. type = Type.GetType(encName);
  434. if(type != null)
  435. {
  436. return (Encoding)(Activator.CreateInstance(type));
  437. }
  438. #endif
  439. // We have no idea how to handle this encoding name.
  440. throw new NotSupportedException
  441. (String.Format(_("NotSupp_EncodingName"), name));
  442. }
  443. #endif // !ECMA_COMPAT
  444. // Get a hash code for this instance.
  445. public override int GetHashCode()
  446. {
  447. return codePage;
  448. }
  449. // Get the maximum number of bytes needed to encode a
  450. // specified number of characters.
  451. public abstract int GetMaxByteCount(int charCount);
  452. // Get the maximum number of characters needed to decode a
  453. // specified number of bytes.
  454. public abstract int GetMaxCharCount(int byteCount);
  455. // Get the identifying preamble for this encoding.
  456. public virtual byte[] GetPreamble()
  457. {
  458. return new byte [0];
  459. }
  460. // Decode a buffer of bytes into a string.
  461. public virtual String GetString(byte[] bytes, int index, int count)
  462. {
  463. return new String(GetChars(bytes, index, count));
  464. }
  465. public virtual String GetString(byte[] bytes)
  466. {
  467. return new String(GetChars(bytes));
  468. }
  469. #if !ECMA_COMPAT
  470. // Get the mail body name for this encoding.
  471. public virtual String BodyName
  472. {
  473. get
  474. {
  475. return null;
  476. }
  477. }
  478. // Get the code page represented by this object.
  479. public virtual int CodePage
  480. {
  481. get
  482. {
  483. return codePage;
  484. }
  485. }
  486. // Get the human-readable name for this encoding.
  487. public virtual String EncodingName
  488. {
  489. get
  490. {
  491. return null;
  492. }
  493. }
  494. // Get the mail agent header name for this encoding.
  495. public virtual String HeaderName
  496. {
  497. get
  498. {
  499. return null;
  500. }
  501. }
  502. // Determine if this encoding can be displayed in a Web browser.
  503. public virtual bool IsBrowserDisplay
  504. {
  505. get
  506. {
  507. return false;
  508. }
  509. }
  510. // Determine if this encoding can be saved from a Web browser.
  511. public virtual bool IsBrowserSave
  512. {
  513. get
  514. {
  515. return false;
  516. }
  517. }
  518. // Determine if this encoding can be displayed in a mail/news agent.
  519. public virtual bool IsMailNewsDisplay
  520. {
  521. get
  522. {
  523. return false;
  524. }
  525. }
  526. // Determine if this encoding can be saved from a mail/news agent.
  527. public virtual bool IsMailNewsSave
  528. {
  529. get
  530. {
  531. return false;
  532. }
  533. }
  534. // Get the IANA-preferred Web name for this encoding.
  535. public virtual String WebName
  536. {
  537. get
  538. {
  539. return null;
  540. }
  541. }
  542. // Get the Windows code page represented by this object.
  543. public virtual int WindowsCodePage
  544. {
  545. get
  546. {
  547. // We make no distinction between normal and
  548. // Windows code pages in this implementation.
  549. return codePage;
  550. }
  551. }
  552. #endif // !ECMA_COMPAT
  553. // Storage for standard encoding objects.
  554. private static Encoding asciiEncoding = null;
  555. private static Encoding bigEndianEncoding = null;
  556. private static Encoding defaultEncoding = null;
  557. private static Encoding utf7Encoding = null;
  558. private static Encoding utf8Encoding = null;
  559. private static Encoding unicodeEncoding = null;
  560. private static Encoding isoLatin1Encoding = null;
  561. // Get the standard ASCII encoding object.
  562. public static Encoding ASCII
  563. {
  564. get
  565. {
  566. lock(typeof(Encoding))
  567. {
  568. if(asciiEncoding == null)
  569. {
  570. asciiEncoding = new ASCIIEncoding();
  571. }
  572. return asciiEncoding;
  573. }
  574. }
  575. }
  576. // Get the standard big-endian Unicode encoding object.
  577. public static Encoding BigEndianUnicode
  578. {
  579. get
  580. {
  581. lock(typeof(Encoding))
  582. {
  583. if(bigEndianEncoding == null)
  584. {
  585. bigEndianEncoding = new UnicodeEncoding(true, true);
  586. }
  587. return bigEndianEncoding;
  588. }
  589. }
  590. }
  591. // Get the default encoding object.
  592. public static Encoding Default
  593. {
  594. get
  595. {
  596. lock(typeof(Encoding))
  597. {
  598. if(defaultEncoding == null)
  599. {
  600. // See if the underlying system knows what
  601. // code page handler we should be using.
  602. int codePage = DefaultEncoding.InternalCodePage();
  603. if(codePage != 0)
  604. {
  605. try
  606. {
  607. defaultEncoding = GetEncoding(codePage);
  608. }
  609. catch(NotSupportedException)
  610. {
  611. defaultEncoding = new DefaultEncoding();
  612. }
  613. }
  614. else
  615. {
  616. defaultEncoding = new DefaultEncoding();
  617. }
  618. }
  619. return defaultEncoding;
  620. }
  621. }
  622. }
  623. // Get the ISO Latin1 encoding object.
  624. private static Encoding ISOLatin1
  625. {
  626. get
  627. {
  628. lock(typeof(Encoding))
  629. {
  630. if(isoLatin1Encoding == null)
  631. {
  632. isoLatin1Encoding = new Latin1Encoding();
  633. }
  634. return isoLatin1Encoding;
  635. }
  636. }
  637. }
  638. // Get the standard UTF-7 encoding object.
  639. #if ECMA_COMPAT
  640. private
  641. #else
  642. public
  643. #endif
  644. static Encoding UTF7
  645. {
  646. get
  647. {
  648. lock(typeof(Encoding))
  649. {
  650. if(utf7Encoding == null)
  651. {
  652. utf7Encoding = new UTF7Encoding();
  653. }
  654. return utf7Encoding;
  655. }
  656. }
  657. }
  658. // Get the standard UTF-8 encoding object.
  659. public static Encoding UTF8
  660. {
  661. get
  662. {
  663. lock(typeof(Encoding))
  664. {
  665. if(utf8Encoding == null)
  666. {
  667. utf8Encoding = new UTF8Encoding();
  668. }
  669. return utf8Encoding;
  670. }
  671. }
  672. }
  673. // Get the standard little-endian Unicode encoding object.
  674. public static Encoding Unicode
  675. {
  676. get
  677. {
  678. lock(typeof(Encoding))
  679. {
  680. if(unicodeEncoding == null)
  681. {
  682. unicodeEncoding = new UnicodeEncoding();
  683. }
  684. return unicodeEncoding;
  685. }
  686. }
  687. }
  688. // Forwarding decoder implementation.
  689. private sealed class ForwardingDecoder : Decoder
  690. {
  691. private Encoding encoding;
  692. // Constructor.
  693. public ForwardingDecoder(Encoding enc)
  694. {
  695. encoding = enc;
  696. }
  697. // Override inherited methods.
  698. public override int GetCharCount(byte[] bytes, int index, int count)
  699. {
  700. return encoding.GetCharCount(bytes, index, count);
  701. }
  702. public override int GetChars(byte[] bytes, int byteIndex,
  703. int byteCount, char[] chars,
  704. int charIndex)
  705. {
  706. return encoding.GetChars(bytes, byteIndex, byteCount,
  707. chars, charIndex);
  708. }
  709. } // class ForwardingDecoder
  710. // Forwarding encoder implementation.
  711. private sealed class ForwardingEncoder : Encoder
  712. {
  713. private Encoding encoding;
  714. // Constructor.
  715. public ForwardingEncoder(Encoding enc)
  716. {
  717. encoding = enc;
  718. }
  719. // Override inherited methods.
  720. public override int GetByteCount(char[] chars, int index,
  721. int count, bool flush)
  722. {
  723. return encoding.GetByteCount(chars, index, count);
  724. }
  725. public override int GetBytes(char[] chars, int charIndex,
  726. int charCount, byte[] bytes,
  727. int byteCount, bool flush)
  728. {
  729. return encoding.GetBytes(chars, charIndex, charCount,
  730. bytes, byteCount);
  731. }
  732. } // class ForwardingEncoder
  733. }; // class Encoding
  734. }; // namespace System.Text