BinHexEncoding.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. //-----------------------------------------------------------------------------
  4. namespace System.Text
  5. {
  6. using System.Globalization;
  7. using System.Runtime;
  8. using System.Runtime.Serialization; //For SR
  9. using System.Security;
  10. class BinHexEncoding : Encoding
  11. {
  12. static byte[] char2val = new byte[128]
  13. {
  14. /* 0-15 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  15. /* 16-31 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  16. /* 32-47 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  17. /* 48-63 */ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  18. /* 64-79 */ 0xFF, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  19. /* 80-95 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  20. /* 96-111 */ 0xFF, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  21. /* 112-127 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  22. };
  23. static string val2char = "0123456789ABCDEF";
  24. #if DEBUG
  25. static BinHexEncoding()
  26. {
  27. for (char ch = '0'; ch <= '9'; ch++)
  28. {
  29. Fx.Assert(char2val[ch] == ch - '0', "");
  30. }
  31. for (char ch = 'A'; ch <= 'F'; ch++)
  32. {
  33. Fx.Assert(char2val[ch] == ch - 'A' + 10, "");
  34. }
  35. for (char ch = 'a'; ch <= 'f'; ch++)
  36. {
  37. Fx.Assert(char2val[ch] == ch - 'a' + 10, "");
  38. }
  39. }
  40. #endif
  41. public override int GetMaxByteCount(int charCount)
  42. {
  43. if (charCount < 0)
  44. throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("charCount", SR.GetString(SR.ValueMustBeNonNegative)));
  45. if ((charCount % 2) != 0)
  46. throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new FormatException(SR.GetString(SR.XmlInvalidBinHexLength, charCount.ToString(NumberFormatInfo.CurrentInfo))));
  47. return charCount / 2;
  48. }
  49. public override int GetByteCount(char[] chars, int index, int count)
  50. {
  51. return GetMaxByteCount(count);
  52. }
  53. [Fx.Tag.SecurityNote(Critical = "Contains unsafe code.",
  54. Safe = "Unsafe code is effectively encapsulated, all inputs are validated.")]
  55. [SecuritySafeCritical]
  56. unsafe public override int GetBytes(char[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex)
  57. {
  58. if (chars == null)
  59. throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("chars"));
  60. if (charIndex < 0)
  61. throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("charIndex", SR.GetString(SR.ValueMustBeNonNegative)));
  62. if (charIndex > chars.Length)
  63. throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("charIndex", SR.GetString(SR.OffsetExceedsBufferSize, chars.Length)));
  64. if (charCount < 0)
  65. throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("charCount", SR.GetString(SR.ValueMustBeNonNegative)));
  66. if (charCount > chars.Length - charIndex)
  67. throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("charCount", SR.GetString(SR.SizeExceedsRemainingBufferSpace, chars.Length - charIndex)));
  68. if (bytes == null)
  69. throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("bytes"));
  70. if (byteIndex < 0)
  71. throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("byteIndex", SR.GetString(SR.ValueMustBeNonNegative)));
  72. if (byteIndex > bytes.Length)
  73. throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("byteIndex", SR.GetString(SR.OffsetExceedsBufferSize, bytes.Length)));
  74. int byteCount = GetByteCount(chars, charIndex, charCount);
  75. if (byteCount < 0 || byteCount > bytes.Length - byteIndex)
  76. throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.XmlArrayTooSmall), "bytes"));
  77. if (charCount > 0)
  78. {
  79. fixed (byte* _char2val = char2val)
  80. {
  81. fixed (byte* _bytes = &bytes[byteIndex])
  82. {
  83. fixed (char* _chars = &chars[charIndex])
  84. {
  85. char* pch = _chars;
  86. char* pchMax = _chars + charCount;
  87. byte* pb = _bytes;
  88. while (pch < pchMax)
  89. {
  90. Fx.Assert(pch + 2 <= pchMax, "");
  91. char pch0 = pch[0];
  92. char pch1 = pch[1];
  93. if ((pch0 | pch1) >= 128)
  94. throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new FormatException(SR.GetString(SR.XmlInvalidBinHexSequence, new string(pch, 0, 2), charIndex + (int)(pch - _chars))));
  95. byte d1 = _char2val[pch0];
  96. byte d2 = _char2val[pch1];
  97. if ((d1 | d2) == 0xFF)
  98. throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new FormatException(SR.GetString(SR.XmlInvalidBinHexSequence, new string(pch, 0, 2), charIndex + (int)(pch - _chars))));
  99. pb[0] = (byte)((d1 << 4) + d2);
  100. pch += 2;
  101. pb++;
  102. }
  103. }
  104. }
  105. }
  106. }
  107. return byteCount;
  108. }
  109. #if NO
  110. public override Encoder GetEncoder()
  111. {
  112. return new BufferedEncoder(this, 2);
  113. }
  114. #endif
  115. public override int GetMaxCharCount(int byteCount)
  116. {
  117. if (byteCount < 0 || byteCount > int.MaxValue / 2)
  118. throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("byteCount", SR.GetString(SR.ValueMustBeInRange, 0, int.MaxValue / 2)));
  119. return byteCount * 2;
  120. }
  121. public override int GetCharCount(byte[] bytes, int index, int count)
  122. {
  123. return GetMaxCharCount(count);
  124. }
  125. [Fx.Tag.SecurityNote(Critical = "Contains unsafe code.",
  126. Safe = "Unsafe code is effectively encapsulated, all inputs are validated.")]
  127. [SecuritySafeCritical]
  128. unsafe public override int GetChars(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex)
  129. {
  130. if (bytes == null)
  131. throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("bytes"));
  132. if (byteIndex < 0)
  133. throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("byteIndex", SR.GetString(SR.ValueMustBeNonNegative)));
  134. if (byteIndex > bytes.Length)
  135. throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("byteIndex", SR.GetString(SR.OffsetExceedsBufferSize, bytes.Length)));
  136. if (byteCount < 0)
  137. throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("byteCount", SR.GetString(SR.ValueMustBeNonNegative)));
  138. if (byteCount > bytes.Length - byteIndex)
  139. throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("byteCount", SR.GetString(SR.SizeExceedsRemainingBufferSpace, bytes.Length - byteIndex)));
  140. int charCount = GetCharCount(bytes, byteIndex, byteCount);
  141. if (chars == null)
  142. throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("chars"));
  143. if (charIndex < 0)
  144. throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("charIndex", SR.GetString(SR.ValueMustBeNonNegative)));
  145. if (charIndex > chars.Length)
  146. throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("charIndex", SR.GetString(SR.OffsetExceedsBufferSize, chars.Length)));
  147. if (charCount < 0 || charCount > chars.Length - charIndex)
  148. throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.XmlArrayTooSmall), "chars"));
  149. if (byteCount > 0)
  150. {
  151. fixed (char* _val2char = val2char)
  152. {
  153. fixed (byte* _bytes = &bytes[byteIndex])
  154. {
  155. fixed (char* _chars = &chars[charIndex])
  156. {
  157. char* pch = _chars;
  158. byte* pb = _bytes;
  159. byte* pbMax = _bytes + byteCount;
  160. while (pb < pbMax)
  161. {
  162. pch[0] = _val2char[pb[0] >> 4];
  163. pch[1] = _val2char[pb[0] & 0x0F];
  164. pb++;
  165. pch += 2;
  166. }
  167. }
  168. }
  169. }
  170. }
  171. return charCount;
  172. }
  173. }
  174. }