The Labs \ Source Viewer \ SSCLI \ System.Xml \ Ucs4Decoder1234

  1. //------------------------------------------------------------------------------
  2. // <copyright file="XmlEncoding.cs" company="Microsoft">
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. // </copyright>
  14. //------------------------------------------------------------------------------
  15. using System.Text;
  16. using System.Diagnostics;
  17. namespace System.Xml
  18. {
  19.    
  20.     internal class UTF16Decoder : System.Text.Decoder
  21.     {
  22.         private bool bigEndian;
  23.         private int lastByte;
  24.         private const int CharSize = 2;
  25.        
  26.         public UTF16Decoder(bool bigEndian)
  27.         {
  28.             this.lastByte = -1;
  29.             this.bigEndian = bigEndian;
  30.         }
  31.        
  32.         public override int GetCharCount(byte[] bytes, int index, int count)
  33.         {
  34.             return GetCharCount(bytes, index, count, false);
  35.         }
  36.        
  37.         public override int GetCharCount(byte[] bytes, int index, int count, bool flush)
  38.         {
  39.             int byteCount = count + ((lastByte >= 0) ? 1 : 0);
  40.             if (flush && (byteCount % CharSize != 0)) {
  41.                 throw new ArgumentException(Res.GetString(Res.Enc_InvalidByteInEncoding, new object[1] {-1}), (string)null);
  42.             }
  43.             return byteCount / CharSize;
  44.         }
  45.        
  46.         public override int GetChars(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex)
  47.         {
  48.             int charCount = GetCharCount(bytes, byteIndex, byteCount);
  49.            
  50.             if (lastByte >= 0) {
  51.                 if (byteCount == 0) {
  52.                     return charCount;
  53.                 }
  54.                 int nextByte = bytes[byteIndex++];
  55.                 byteCount--;
  56.                
  57.                 chars[charIndex++] = bigEndian ? (char)(lastByte << 8 | nextByte) : (char)(nextByte << 8 | lastByte);
  58.                 lastByte = -1;
  59.             }
  60.            
  61.             if ((byteCount & 1) != 0) {
  62.                 lastByte = bytes[byteIndex + --byteCount];
  63.             }
  64.            
  65.             // use the fast BlockCopy if possible
  66.             if (bigEndian == BitConverter.IsLittleEndian) {
  67.                 int byteEnd = byteIndex + byteCount;
  68.                 if (bigEndian) {
  69.                     while (byteIndex < byteEnd) {
  70.                         int hi = bytes[byteIndex++];
  71.                         int lo = bytes[byteIndex++];
  72.                         chars[charIndex++] = (char)(hi << 8 | lo);
  73.                     }
  74.                 }
  75.                 else {
  76.                     while (byteIndex < byteEnd) {
  77.                         int lo = bytes[byteIndex++];
  78.                         int hi = bytes[byteIndex++];
  79.                         chars[charIndex++] = (char)(hi << 8 | lo);
  80.                     }
  81.                 }
  82.             }
  83.             else {
  84.                 Buffer.BlockCopy(bytes, byteIndex, chars, charIndex * CharSize, byteCount);
  85.             }
  86.             return charCount;
  87.         }
  88.        
  89.         public override void Convert(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex, int charCount, bool flush, out int bytesUsed, out int charsUsed, out bool completed
  90.         )
  91.         {
  92.             charsUsed = 0;
  93.             bytesUsed = 0;
  94.            
  95.             if (lastByte >= 0) {
  96.                 if (byteCount == 0) {
  97.                     completed = true;
  98.                     return;
  99.                 }
  100.                 int nextByte = bytes[byteIndex++];
  101.                 byteCount--;
  102.                 bytesUsed++;
  103.                
  104.                 chars[charIndex++] = bigEndian ? (char)(lastByte << 8 | nextByte) : (char)(nextByte << 8 | lastByte);
  105.                 charCount--;
  106.                 charsUsed++;
  107.                 lastByte = -1;
  108.             }
  109.            
  110.             if (charCount * CharSize < byteCount) {
  111.                 byteCount = charCount * CharSize;
  112.                 completed = false;
  113.             }
  114.             else {
  115.                 completed = true;
  116.             }
  117.            
  118.             if (bigEndian == BitConverter.IsLittleEndian) {
  119.                 int i = byteIndex;
  120.                 int byteEnd = i + (byteCount & ~1);
  121.                 if (bigEndian) {
  122.                     while (i < byteEnd) {
  123.                         int hi = bytes[i++];
  124.                         int lo = bytes[i++];
  125.                         chars[charIndex++] = (char)(hi << 8 | lo);
  126.                     }
  127.                 }
  128.                 else {
  129.                     while (i < byteEnd) {
  130.                         int lo = bytes[i++];
  131.                         int hi = bytes[i++];
  132.                         chars[charIndex++] = (char)(hi << 8 | lo);
  133.                     }
  134.                 }
  135.             }
  136.             else {
  137.                 Buffer.BlockCopy(bytes, byteIndex, chars, charIndex * CharSize, (int)(byteCount & ~1));
  138.             }
  139.             charsUsed += byteCount / CharSize;
  140.             bytesUsed += byteCount;
  141.            
  142.             if ((byteCount & 1) != 0) {
  143.                 lastByte = bytes[byteIndex + byteCount - 1];
  144.             }
  145.         }
  146.     }
  147.    
  148.     internal class SafeAsciiDecoder : Decoder
  149.     {
  150.        
  151.         public SafeAsciiDecoder()
  152.         {
  153.         }
  154.        
  155.         public override int GetCharCount(byte[] bytes, int index, int count)
  156.         {
  157.             return count;
  158.         }
  159.        
  160.         public override int GetChars(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex)
  161.         {
  162.             int i = byteIndex;
  163.             int j = charIndex;
  164.             while (i < byteIndex + byteCount) {
  165.                 chars[j++] = (char)bytes[i++];
  166.             }
  167.             return byteCount;
  168.         }
  169.        
  170.         public override void Convert(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex, int charCount, bool flush, out int bytesUsed, out int charsUsed, out bool completed
  171.         )
  172.         {
  173.             if (charCount < byteCount) {
  174.                 byteCount = charCount;
  175.                 completed = false;
  176.             }
  177.             else {
  178.                 completed = true;
  179.             }
  180.            
  181.             int i = byteIndex;
  182.             int j = charIndex;
  183.             int byteEndIndex = byteIndex + byteCount;
  184.            
  185.             while (i < byteEndIndex) {
  186.                 chars[j++] = (char)bytes[i++];
  187.             }
  188.            
  189.             charsUsed = byteCount;
  190.             bytesUsed = byteCount;
  191.         }
  192.     }
  193.    
  194.     internal class Ucs4Encoding : Encoding
  195.     {
  196.         internal Ucs4Decoder ucs4Decoder;
  197.        
  198.         public override Decoder GetDecoder()
  199.         {
  200.             return ucs4Decoder;
  201.         }
  202.        
  203.         public override int GetByteCount(char[] chars, int index, int count)
  204.         {
  205.             return checked(count * 4);
  206.         }
  207.        
  208.         public override int GetByteCount(char[] chars)
  209.         {
  210.             return chars.Length * 4;
  211.         }
  212.        
  213.         public override byte[] GetBytes(string s)
  214.         {
  215.             return null;
  216.             //ucs4Decoder.GetByteCount(chars, index, count);
  217.         }
  218.         public override int GetBytes(char[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex)
  219.         {
  220.             return 0;
  221.         }
  222.         public override int GetMaxByteCount(int charCount)
  223.         {
  224.             return 0;
  225.         }
  226.        
  227.         public override int GetCharCount(byte[] bytes, int index, int count)
  228.         {
  229.             return ucs4Decoder.GetCharCount(bytes, index, count);
  230.         }
  231.        
  232.         public override int GetChars(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex)
  233.         {
  234.             return ucs4Decoder.GetChars(bytes, byteIndex, byteCount, chars, charIndex);
  235.         }
  236.        
  237.         public override int GetMaxCharCount(int byteCount)
  238.         {
  239.             return (byteCount + 3) / 4;
  240.         }
  241.        
  242.         public override int CodePage {
  243.             get { return 0; }
  244.         }
  245.        
  246.         public override int GetCharCount(byte[] bytes)
  247.         {
  248.             return bytes.Length / 4;
  249.         }
  250.        
  251.         public override Encoder GetEncoder()
  252.         {
  253.             return null;
  254.         }
  255.        
  256.         static internal Encoding UCS4_Littleendian {
  257.             get { return new Ucs4Encoding4321(); }
  258.         }
  259.        
  260.         static internal Encoding UCS4_Bigendian {
  261.             get { return new Ucs4Encoding1234(); }
  262.         }
  263.        
  264.         static internal Encoding UCS4_2143 {
  265.             get { return new Ucs4Encoding2143(); }
  266.         }
  267.         static internal Encoding UCS4_3412 {
  268.             get { return new Ucs4Encoding3412(); }
  269.         }
  270.     }
  271.    
  272.     internal class Ucs4Encoding1234 : Ucs4Encoding
  273.     {
  274.        
  275.         public Ucs4Encoding1234()
  276.         {
  277.             ucs4Decoder = new Ucs4Decoder1234();
  278.         }
  279.        
  280.         public override string EncodingName {
  281.             get { return "ucs-4 (Bigendian)"; }
  282.         }
  283.        
  284.         public override byte[] GetPreamble()
  285.         {
  286.             return new byte[4] {0, 0, 254, 255};
  287.         }
  288.     }
  289.    
  290.     internal class Ucs4Encoding4321 : Ucs4Encoding
  291.     {
  292.         public Ucs4Encoding4321()
  293.         {
  294.             ucs4Decoder = new Ucs4Decoder4321();
  295.         }
  296.        
  297.         public override string EncodingName {
  298.             get { return "ucs-4"; }
  299.         }
  300.        
  301.         public override byte[] GetPreamble()
  302.         {
  303.             return new byte[4] {255, 254, 0, 0};
  304.         }
  305.     }
  306.    
  307.     internal class Ucs4Encoding2143 : Ucs4Encoding
  308.     {
  309.         public Ucs4Encoding2143()
  310.         {
  311.             ucs4Decoder = new Ucs4Decoder2143();
  312.         }
  313.        
  314.         public override string EncodingName {
  315.             get { return "ucs-4 (order 2143)"; }
  316.         }
  317.         public override byte[] GetPreamble()
  318.         {
  319.             return new byte[4] {0, 0, 255, 254};
  320.         }
  321.     }
  322.    
  323.     internal class Ucs4Encoding3412 : Ucs4Encoding
  324.     {
  325.         public Ucs4Encoding3412()
  326.         {
  327.             ucs4Decoder = new Ucs4Decoder3412();
  328.         }
  329.        
  330.         public override string EncodingName {
  331.             get { return "ucs-4 (order 3412)"; }
  332.         }
  333.        
  334.         public override byte[] GetPreamble()
  335.         {
  336.             return new byte[4] {254, 255, 0, 0};
  337.         }
  338.     }
  339.    
  340.     internal abstract class Ucs4Decoder : Decoder
  341.     {
  342.        
  343.         internal byte[] lastBytes = new byte[4];
  344.         internal int lastBytesCount = 0;
  345.        
  346.         public override int GetCharCount(byte[] bytes, int index, int count)
  347.         {
  348.             return (count + lastBytesCount) / 4;
  349.         }
  350.        
  351.         internal abstract int GetFullChars(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex);
  352.        
  353.         public override int GetChars(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex)
  354.         {
  355.             // finish a character from the bytes that were cached last time
  356.             int i = lastBytesCount;
  357.             if (lastBytesCount > 0) {
  358.                 // copy remaining bytes into the cache
  359.                 for (; lastBytesCount < 4 && byteCount > 0; lastBytesCount++) {
  360.                     lastBytes[lastBytesCount] = bytes[byteIndex];
  361.                     byteIndex++;
  362.                     byteCount--;
  363.                 }
  364.                 // still not enough bytes -> return
  365.                 if (lastBytesCount < 4) {
  366.                     return 0;
  367.                 }
  368.                 // decode 1 character from the byte cache
  369.                 i = GetFullChars(lastBytes, 0, 4, chars, charIndex);
  370.                 Debug.Assert(i == 1);
  371.                 charIndex += i;
  372.                 lastBytesCount = 0;
  373.             }
  374.             else {
  375.                 i = 0;
  376.             }
  377.            
  378.             // decode block of byte quadruplets
  379.             i = GetFullChars(bytes, byteIndex, byteCount, chars, charIndex) + i;
  380.            
  381.             // cache remaining bytes that does not make up a character
  382.             int bytesLeft = (byteCount & 3);
  383.             if (bytesLeft >= 0) {
  384.                 for (int j = 0; j < bytesLeft; j++) {
  385.                     lastBytes[j] = bytes[byteIndex + byteCount - bytesLeft + j];
  386.                 }
  387.                 lastBytesCount = bytesLeft;
  388.             }
  389.             return i;
  390.         }
  391.        
  392.         public override void Convert(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex, int charCount, bool flush, out int bytesUsed, out int charsUsed, out bool completed
  393.         )
  394.         {
  395.             bytesUsed = 0;
  396.             charsUsed = 0;
  397.             // finish a character from the bytes that were cached last time
  398.             int i = 0;
  399.             int lbc = lastBytesCount;
  400.             if (lbc > 0) {
  401.                 // copy remaining bytes into the cache
  402.                 for (; lbc < 4 && byteCount > 0; lbc++) {
  403.                     lastBytes[lbc] = bytes[byteIndex];
  404.                     byteIndex++;
  405.                     byteCount--;
  406.                     bytesUsed++;
  407.                 }
  408.                 // still not enough bytes -> return
  409.                 if (lbc < 4) {
  410.                     lastBytesCount = lbc;
  411.                     completed = true;
  412.                     return;
  413.                 }
  414.                 // decode 1 character from the byte cache
  415.                 i = GetFullChars(lastBytes, 0, 4, chars, charIndex);
  416.                 Debug.Assert(i == 1);
  417.                 charIndex += i;
  418.                 charCount -= i;
  419.                 charsUsed = i;
  420.                
  421.                 lastBytesCount = 0;
  422.                
  423.                 // if that's all that was requested -> return
  424.                 if (charCount == 0) {
  425.                     completed = (byteCount == 0);
  426.                     return;
  427.                 }
  428.             }
  429.             else {
  430.                 i = 0;
  431.             }
  432.            
  433.             // modify the byte count for GetFullChars depending on how many characters were requested
  434.             if (charCount * 4 < byteCount) {
  435.                 byteCount = charCount * 4;
  436.                 completed = false;
  437.             }
  438.             else {
  439.                 completed = true;
  440.             }
  441.             bytesUsed += byteCount;
  442.            
  443.             // decode block of byte quadruplets
  444.             charsUsed = GetFullChars(bytes, byteIndex, byteCount, chars, charIndex) + i;
  445.            
  446.             // cache remaining bytes that does not make up a character
  447.             int bytesLeft = (byteCount & 3);
  448.             if (bytesLeft >= 0) {
  449.                 for (int j = 0; j < bytesLeft; j++) {
  450.                     lastBytes[j] = bytes[byteIndex + byteCount - bytesLeft + j];
  451.                 }
  452.                 lastBytesCount = bytesLeft;
  453.             }
  454.         }
  455.        
  456.         internal char UnicodeToUTF16(uint code)
  457.         {
  458.             byte lowerByte;
  459.             byte higherByte;
  460.             lowerByte = (byte)(55232 + (code >> 10));
  461.             higherByte = (byte)(56320 | code & 1023);
  462.             return ((char)((higherByte << 8) | lowerByte));
  463.         }
  464.     }
  465.    
  466.     internal class Ucs4Decoder4321 : Ucs4Decoder
  467.     {
  468.        
  469.         internal override int GetFullChars(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex)
  470.         {
  471.             uint code;
  472.             int i;
  473.             int j;
  474.            
  475.             byteCount += byteIndex;
  476.            
  477.             for (i = byteIndex,j = charIndex; i + 3 < byteCount;) {
  478.                 code = (uint)((bytes[i + 3] << 24) | (bytes[i + 2] << 16) | (bytes[i + 1] << 8) | bytes[i]);
  479.                 if (code > 1114111) {
  480.                     throw new ArgumentException(Res.GetString(Res.Enc_InvalidByteInEncoding, new object[1] {i}), (string)null);
  481.                 }
  482.                 else if (code > 65535) {
  483.                     chars[j] = UnicodeToUTF16(code);
  484.                     j++;
  485.                 }
  486.                 else {
  487.                     if (code >= 55296 && code <= 57343) {
  488.                         throw new XmlException(Res.Xml_InvalidCharInThisEncoding, string.Empty);
  489.                     }
  490.                     else {
  491.                         chars[j] = (char)code;
  492.                     }
  493.                 }
  494.                 j++;
  495.                 i += 4;
  496.             }
  497.             return j - charIndex;
  498.         }
  499.     }
  500.    
  501.     internal class Ucs4Decoder1234 : Ucs4Decoder
  502.     {
  503.        
  504.         internal override int GetFullChars(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex)
  505.         {
  506.             uint code;
  507.             int i;
  508.             int j;
  509.            
  510.             byteCount += byteIndex;
  511.            
  512.             for (i = byteIndex,j = charIndex; i + 3 < byteCount;) {
  513.                 code = (uint)((bytes[i] << 24) | (bytes[i + 1] << 16) | (bytes[i + 2] << 8) | bytes[i + 3]);
  514.                 if (code > 1114111) {
  515.                     throw new ArgumentException(Res.GetString(Res.Enc_InvalidByteInEncoding, new object[1] {i}), (string)null);
  516.                 }
  517.                 else if (code > 65535) {
  518.                     chars[j] = UnicodeToUTF16(code);
  519.                     j++;
  520.                 }
  521.                 else {
  522.                     if (code >= 55296 && code <= 57343) {
  523.                         throw new XmlException(Res.Xml_InvalidCharInThisEncoding, string.Empty);
  524.                     }
  525.                     else {
  526.                         chars[j] = (char)code;
  527.                     }
  528.                 }
  529.                 j++;
  530.                 i += 4;
  531.             }
  532.             return j - charIndex;
  533.         }
  534.     }
  535.    
  536.    
  537.     internal class Ucs4Decoder2143 : Ucs4Decoder
  538.     {
  539.        
  540.         internal override int GetFullChars(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex)
  541.         {
  542.             uint code;
  543.             int i;
  544.             int j;
  545.            
  546.             byteCount += byteIndex;
  547.            
  548.             for (i = byteIndex,j = charIndex; i + 3 < byteCount;) {
  549.                 code = (uint)((bytes[i + 1] << 24) | (bytes[i] << 16) | (bytes[i + 3] << 8) | bytes[i + 2]);
  550.                 if (code > 1114111) {
  551.                     throw new ArgumentException(Res.GetString(Res.Enc_InvalidByteInEncoding, new object[1] {i}), (string)null);
  552.                 }
  553.                 else if (code > 65535) {
  554.                     chars[j] = UnicodeToUTF16(code);
  555.                     j++;
  556.                 }
  557.                 else {
  558.                     if (code >= 55296 && code <= 57343) {
  559.                         throw new XmlException(Res.Xml_InvalidCharInThisEncoding, string.Empty);
  560.                     }
  561.                     else {
  562.                         chars[j] = (char)code;
  563.                     }
  564.                 }
  565.                 j++;
  566.                 i += 4;
  567.             }
  568.             return j - charIndex;
  569.         }
  570.     }
  571.    
  572.    
  573.     internal class Ucs4Decoder3412 : Ucs4Decoder
  574.     {
  575.        
  576.         internal override int GetFullChars(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex)
  577.         {
  578.             uint code;
  579.             int i;
  580.             int j;
  581.            
  582.             byteCount += byteIndex;
  583.            
  584.             for (i = byteIndex,j = charIndex; i + 3 < byteCount;) {
  585.                 code = (uint)((bytes[i + 2] << 24) | (bytes[i + 3] << 16) | (bytes[i] << 8) | bytes[i + 1]);
  586.                 if (code > 1114111) {
  587.                     throw new ArgumentException(Res.GetString(Res.Enc_InvalidByteInEncoding, new object[1] {i}), (string)null);
  588.                 }
  589.                 else if (code > 65535) {
  590.                     chars[j] = UnicodeToUTF16(code);
  591.                     j++;
  592.                 }
  593.                 else {
  594.                     if (code >= 55296 && code <= 57343) {
  595.                         throw new XmlException(Res.Xml_InvalidCharInThisEncoding, string.Empty);
  596.                     }
  597.                     else {
  598.                         chars[j] = (char)code;
  599.                     }
  600.                 }
  601.                 j++;
  602.                 i += 4;
  603.             }
  604.             return j - charIndex;
  605.         }
  606.     }
  607. }

Developer Fusion