Showing the changes to Source/Libraries/GSF.Core/ByteEncoding.cs (1 of 628 files). Show all
Unified · Split
| @@ -0,0 +1,767 @@ | |||
| 1 | //****************************************************************************************************** | ||
| 2 | // ByteEncoding.cs - Gbtc | ||
| 3 | // | ||
| 4 | // Copyright � 2010, Grid Protection Alliance. All Rights Reserved. | ||
| 5 | // | ||
| 6 | // Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See | ||
| 7 | // the NOTICE file distributed with this work for additional information regarding copyright ownership. | ||
| 8 | // The GPA licenses this file to you under the Eclipse Public License -v 1.0 (the "License"); you may | ||
| 9 | // not use this file except in compliance with the License. You may obtain a copy of the License at: | ||
| 10 | // | ||
| 11 | // http://www.opensource.org/licenses/eclipse-1.0.php | ||
| 12 | // | ||
| 13 | // Unless agreed to in writing, the subject software distributed under the License is distributed on an | ||
| 14 | // "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the | ||
| 15 | // License for the specific language governing permissions and limitations. | ||
| 16 | // | ||
| 17 | // Code Modification History: | ||
| 18 | // ---------------------------------------------------------------------------------------------------- | ||
| 19 | // 01/25/2008 - J. Ritchie Carroll | ||
| 20 | // Initial version of source generated. | ||
| 21 | // 09/14/2009 - Stephen C. Wills | ||
| 22 | // Added new header and license agreement. | ||
| 23 | // 10/8/2012 - Danyelle Gilliam | ||
| 24 | // Modified Header | ||
| 25 | // | ||
| 26 | //****************************************************************************************************** | ||
| 27 | |||
| 28 | |||
| 29 | |||
| 30 | |||
| 31 | #region [ Contributor License Agreements ] | ||
| 32 | |||
| 33 | /**************************************************************************\ | ||
| 34 | Copyright � 2009 - J. Ritchie Carroll | ||
| 35 | All rights reserved. | ||
| 36 | |||
| 37 | Redistribution and use in source and binary forms, with or without | ||
| 38 | modification, are permitted provided that the following conditions | ||
| 39 | are met: | ||
| 40 | |||
| 41 | * Redistributions of source code must retain the above copyright | ||
| 42 | notice, this list of conditions and the following disclaimer. | ||
| 43 | |||
| 44 | * Redistributions in binary form must reproduce the above | ||
| 45 | copyright notice, this list of conditions and the following | ||
| 46 | disclaimer in the documentation and/or other materials provided | ||
| 47 | with the distribution. | ||
| 48 | |||
| 49 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY | ||
| 50 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
| 51 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | ||
| 52 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | ||
| 53 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | ||
| 54 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | ||
| 55 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | ||
| 56 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY | ||
| 57 | OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
| 58 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
| 59 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
| 60 | |||
| 61 | \**************************************************************************/ | ||
| 62 | |||
| 63 | #endregion | ||
| 64 | |||
| 65 | using System; | ||
| 66 | using System.ComponentModel; | ||
| 67 | using System.Text; | ||
| 68 | using System.Text.RegularExpressions; | ||
| 69 | |||
| 70 | namespace GSF | ||
| 71 | { | ||
| 72 | /// <summary> | ||
| 73 | /// Defines a set of methods used to convert byte buffers to and from user presentable data formats. | ||
| 74 | /// </summary> | ||
| 75 | public abstract class ByteEncoding | ||
| 76 | { | ||
| 77 | #region [ Members ] | ||
| 78 | |||
| 79 | // Nested Types | ||
| 80 | #region [ Hexadecimal Encoding Class ] | ||
| 81 | |||
| 82 | /// <summary> | ||
| 83 | /// Handles conversion of byte buffers to and from a hexadecimal data format. | ||
| 84 | /// </summary> | ||
| 85 | [EditorBrowsable(EditorBrowsableState.Never)] | ||
| 86 | public class HexadecimalEncoding : ByteEncoding | ||
| 87 | { | ||
| 88 | internal HexadecimalEncoding() | ||
| 89 | { | ||
| 90 | // This class is meant for internal instatiation only. | ||
| 91 | } | ||
| 92 | |||
| 93 | /// <summary>Decodes given string back into a byte buffer.</summary> | ||
| 94 | /// <param name="hexData">Encoded hexadecimal data string to decode.</param> | ||
| 95 | /// <param name="spacingCharacter">Original spacing character that was inserted between encoded bytes.</param> | ||
| 96 | /// <returns>Decoded bytes.</returns> | ||
| 97 | public override byte[] GetBytes(string hexData, char spacingCharacter) | ||
| 98 | { | ||
| 99 | if (!string.IsNullOrEmpty(hexData)) | ||
| 100 | { | ||
| 101 | // Removes spacing characters, if needed. | ||
| 102 | hexData = hexData.Trim(); | ||
| 103 | if (spacingCharacter != NoSpacing) | ||
| 104 | hexData = hexData.Replace(spacingCharacter.ToString(), ""); | ||
| 105 | |||
| 106 | // Processes the string only if it has data in hex format (Example: 48 65 6C 6C 21). | ||
| 107 | if (Regex.Matches(hexData, "[^a-fA-F0-9]").Count == 0) | ||
| 108 | { | ||
| 109 | // Trims the end of the string to discard any additional characters, if present in the string, | ||
| 110 | // that would prevent the string from being a hex encoded string. | ||
| 111 | // Note: Requires that each character be represented by its 2 character hex value. | ||
| 112 | hexData = hexData.Substring(0, hexData.Length - hexData.Length % 2); | ||
| 113 | |||
| 114 | byte[] bytes = new byte[hexData.Length / 2]; | ||
| 115 | int index = 0; | ||
| 116 | |||
| 117 | for (int x = 0; x <= hexData.Length - 1; x += 2) | ||
| 118 | { | ||
| 119 | bytes[index] = Convert.ToByte(hexData.Substring(x, 2), 16); | ||
| 120 | index++; | ||
| 121 | } | ||
| 122 | |||
| 123 | return bytes; | ||
| 124 | } | ||
| 125 | else | ||
| 126 | { | ||
| 127 | throw new ArgumentException("Input string is not a valid hex encoded string - invalid characters encountered", "hexData"); | ||
| 128 | } | ||
| 129 | } | ||
| 130 | else | ||
| 131 | { | ||
| 132 | throw new ArgumentNullException("hexData", "Input string cannot be null or empty"); | ||
| 133 | } | ||
| 134 | } | ||
| 135 | |||
| 136 | /// <summary>Encodes given buffer into a user presentable representation.</summary> | ||
| 137 | /// <param name="bytes">Bytes to encode.</param> | ||
| 138 | /// <param name="offset">Offset into buffer to begin encoding.</param> | ||
| 139 | /// <param name="length">Length of buffer to encode.</param> | ||
| 140 | /// <param name="spacingCharacter">Spacing character to place between encoded bytes.</param> | ||
| 141 | /// <returns>String of encoded bytes.</returns> | ||
| 142 | public override string GetString(byte[] bytes, int offset, int length, char spacingCharacter) | ||
| 143 | { | ||
| 144 | return BytesToString(bytes, offset, length, spacingCharacter, "X2"); | ||
| 145 | } | ||
| 146 | } | ||
| 147 | |||
| 148 | #endregion | ||
| 149 | |||
| 150 | #region [ Decimal Encoding Class ] | ||
| 151 | |||
| 152 | /// <summary> | ||
| 153 | /// Handles conversion of byte buffers to and from a decimal data format. | ||
| 154 | /// </summary> | ||
| 155 | [EditorBrowsable(EditorBrowsableState.Never)] | ||
| 156 | public class DecimalEncoding : ByteEncoding | ||
| 157 | { | ||
| 158 | internal DecimalEncoding() | ||
| 159 | { | ||
| 160 | // This class is meant for internal instatiation only. | ||
| 161 | } | ||
| 162 | |||
| 163 | /// <summary>Decodes given string back into a byte buffer.</summary> | ||
| 164 | /// <param name="decData">Encoded decimal data string to decode.</param> | ||
| 165 | /// <param name="spacingCharacter">Original spacing character that was inserted between encoded bytes.</param> | ||
| 166 | /// <returns>Decoded bytes.</returns> | ||
| 167 | public override byte[] GetBytes(string decData, char spacingCharacter) | ||
| 168 | { | ||
| 169 | if (!string.IsNullOrEmpty(decData)) | ||
| 170 | { | ||
| 171 | // Removes spacing characters, if needed. | ||
| 172 | decData = decData.Trim(); | ||
| 173 | if (spacingCharacter != NoSpacing) | ||
| 174 | decData = decData.Replace(spacingCharacter.ToString(), ""); | ||
| 175 | |||
| 176 | // Processes the string only if it has data in decimal format (Example: 072 101 108 108 033). | ||
| 177 | if (Regex.Matches(decData, "[^0-9]").Count == 0) | ||
| 178 | { | ||
| 179 | // Trims the end of the string to discard any additional characters, if present in the | ||
| 180 | // string, that would prevent the string from being an integer encoded string. | ||
| 181 | // Note: Requires that each character be represented by its 3 character decimal value. | ||
| 182 | decData = decData.Substring(0, decData.Length - decData.Length % 3); | ||
| 183 | |||
| 184 | byte[] bytes = new byte[decData.Length / 3]; | ||
| 185 | int index = 0; | ||
| 186 | |||
| 187 | for (int x = 0; x <= decData.Length - 1; x += 3) | ||
| 188 | { | ||
| 189 | bytes[index] = Convert.ToByte(decData.Substring(x, 3), 10); | ||
| 190 | index++; | ||
| 191 | } | ||
| 192 | |||
| 193 | return bytes; | ||
| 194 | } | ||
| 195 | else | ||
| 196 | { | ||
| 197 | throw new ArgumentException("Input string is not a valid decimal encoded string - invalid characters encountered", "decData"); | ||
| 198 | } | ||
| 199 | } | ||
| 200 | else | ||
| 201 | { | ||
| 202 | throw new ArgumentNullException("decData", "Input string cannot be null or empty"); | ||
| 203 | } | ||
| 204 | } | ||
| 205 | |||
| 206 | /// <summary>Encodes given buffer into a user presentable representation.</summary> | ||
| 207 | /// <param name="bytes">Bytes to encode.</param> | ||
| 208 | /// <param name="offset">Offset into buffer to begin encoding.</param> | ||
| 209 | /// <param name="length">Length of buffer to encode.</param> | ||
| 210 | /// <param name="spacingCharacter">Spacing character to place between encoded bytes.</param> | ||
| 211 | /// <returns>String of encoded bytes.</returns> | ||
| 212 | public override string GetString(byte[] bytes, int offset, int length, char spacingCharacter) | ||
| 213 | { | ||
| 214 | return BytesToString(bytes, offset, length, spacingCharacter, "D3"); | ||
| 215 | } | ||
| 216 | } | ||
| 217 | |||
| 218 | #endregion | ||
| 219 | |||
| 220 | #region [ Binary Encoding Class ] | ||
| 221 | |||
| 222 | /// <summary> | ||
| 223 | /// Handles conversion of byte buffers to and from a binary (i.e., 0 and 1's) data format. | ||
| 224 | /// </summary> | ||
| 225 | [EditorBrowsable(EditorBrowsableState.Never)] | ||
| 226 | public class BinaryEncoding : ByteEncoding | ||
| 227 | { | ||
| 228 | private string[] m_byteImages; | ||
| 229 | private bool m_reverse; | ||
| 230 | |||
| 231 | // This class is meant for internal instantiation only. | ||
| 232 | internal BinaryEncoding(Endianness targetEndianness) | ||
| 233 | { | ||
| 234 | if (targetEndianness == Endianness.BigEndian) | ||
| 235 | { | ||
| 236 | if (BitConverter.IsLittleEndian) | ||
| 237 | { | ||
| 238 | // If OS is little endian and we want big endian, this reverses the bit order. | ||
| 239 | m_reverse = true; | ||
| 240 | } | ||
| 241 | else | ||
| 242 | { | ||
| 243 | // If OS is big endian and we want big endian, this keeps the OS bit order. | ||
| 244 | m_reverse = false; | ||
| 245 | } | ||
| 246 | } | ||
| 247 | else | ||
| 248 | { | ||
| 249 | if (BitConverter.IsLittleEndian) | ||
| 250 | { | ||
| 251 | // If OS is little endian and we want little endian, this keeps OS bit order. | ||
| 252 | m_reverse = false; | ||
| 253 | } | ||
| 254 | else | ||
| 255 | { | ||
| 256 | // If OS is big endian and we want little endian, this reverses the bit order. | ||
| 257 | m_reverse = true; | ||
| 258 | } | ||
| 259 | } | ||
| 260 | } | ||
| 261 | |||
| 262 | /// <summary>Decodes given string back into a byte buffer.</summary> | ||
| 263 | /// <param name="binaryData">Encoded binary data string to decode.</param> | ||
| 264 | /// <param name="spacingCharacter">Original spacing character that was inserted between encoded bytes.</param> | ||
| 265 | /// <returns>Decoded bytes.</returns> | ||
| 266 | public override byte[] GetBytes(string binaryData, char spacingCharacter) | ||
| 267 | { | ||
| 268 | if (!string.IsNullOrEmpty(binaryData)) | ||
| 269 | { | ||
| 270 | // Removes spacing characters, if needed. | ||
| 271 | binaryData = binaryData.Trim(); | ||
| 272 | if (spacingCharacter != NoSpacing) | ||
| 273 | binaryData = binaryData.Replace(spacingCharacter.ToString(), ""); | ||
| 274 | |||
| 275 | // Processes the string only if it has data in binary format (Example: 01010110 1010101). | ||
| 276 | if (Regex.Matches(binaryData, "[^0-1]").Count == 0) | ||
| 277 | { | ||
| 278 | // Trims the end of the string to discard any additional characters, if present in the | ||
| 279 | // string, that would prevent the string from being a binary encoded string. | ||
| 280 | // Note: Requires each character be represented by its 8 character binary value. | ||
| 281 | binaryData = binaryData.Substring(0, binaryData.Length - binaryData.Length % 8); | ||
| 282 | |||
| 283 | byte[] bytes = new byte[binaryData.Length / 8]; | ||
| 284 | int index = 0; | ||
| 285 | |||
| 286 | for (int x = 0; x <= binaryData.Length - 1; x += 8) | ||
| 287 | { | ||
| 288 | bytes[index] = (byte)Bits.Nil; | ||
| 289 | |||
| 290 | if (m_reverse) | ||
| 291 | { | ||
| 292 | if (binaryData[x + 7] == '1') | ||
| 293 | bytes[index] = bytes[index].SetBits(Bits.Bit00); | ||
| 294 | if (binaryData[x + 6] == '1') | ||
| 295 | bytes[index] = bytes[index].SetBits(Bits.Bit01); | ||
| 296 | if (binaryData[x + 5] == '1') | ||
| 297 | bytes[index] = bytes[index].SetBits(Bits.Bit02); | ||
| 298 | if (binaryData[x + 4] == '1') | ||
| 299 | bytes[index] = bytes[index].SetBits(Bits.Bit03); | ||
| 300 | if (binaryData[x + 3] == '1') | ||
| 301 | bytes[index] = bytes[index].SetBits(Bits.Bit04); | ||
| 302 | if (binaryData[x + 2] == '1') | ||
| 303 | bytes[index] = bytes[index].SetBits(Bits.Bit05); | ||
| 304 | if (binaryData[x + 1] == '1') | ||
| 305 | bytes[index] = bytes[index].SetBits(Bits.Bit06); | ||
| 306 | if (binaryData[x + 0] == '1') | ||
| 307 | bytes[index] = bytes[index].SetBits(Bits.Bit07); | ||
| 308 | } | ||
| 309 | else | ||
| 310 | { | ||
| 311 | if (binaryData[x + 0] == '1') | ||
| 312 | bytes[index] = bytes[index].SetBits(Bits.Bit00); | ||
| 313 | if (binaryData[x + 1] == '1') | ||
| 314 | bytes[index] = bytes[index].SetBits(Bits.Bit01); | ||
| 315 | if (binaryData[x + 2] == '1') | ||
| 316 | bytes[index] = bytes[index].SetBits(Bits.Bit02); | ||
| 317 | if (binaryData[x + 3] == '1') | ||
| 318 | bytes[index] = bytes[index].SetBits(Bits.Bit03); | ||
| 319 | if (binaryData[x + 4] == '1') | ||
| 320 | bytes[index] = bytes[index].SetBits(Bits.Bit04); | ||
| 321 | if (binaryData[x + 5] == '1') | ||
| 322 | bytes[index] = bytes[index].SetBits(Bits.Bit05); | ||
| 323 | if (binaryData[x + 6] == '1') | ||
| 324 | bytes[index] = bytes[index].SetBits(Bits.Bit06); | ||
| 325 | if (binaryData[x + 7] == '1') | ||
| 326 | bytes[index] = bytes[index].SetBits(Bits.Bit07); | ||
| 327 | } | ||
| 328 | |||
| 329 | index++; | ||
| 330 | } | ||
| 331 | |||
| 332 | return bytes; | ||
| 333 | } | ||
| 334 | else | ||
| 335 | { | ||
| 336 | throw new ArgumentException("Input string is not a valid binary encoded string - invalid characters encountered", "binaryData"); | ||
| 337 | } | ||
| 338 | } | ||
| 339 | else | ||
| 340 | { | ||
| 341 | throw new ArgumentNullException("binaryData", "Input string cannot be null or empty"); | ||
| 342 | } | ||
| 343 | } | ||
| 344 | |||
| 345 | /// <summary>Encodes given buffer into a user presentable representation.</summary> | ||
| 346 | /// <param name="bytes">Bytes to encode.</param> | ||
| 347 | /// <param name="offset">Offset into buffer to begin encoding.</param> | ||
| 348 | /// <param name="length">Length of buffer to encode.</param> | ||
| 349 | /// <param name="spacingCharacter">Spacing character to place between encoded bytes.</param> | ||
| 350 | /// <returns>String of encoded bytes.</returns> | ||
| 351 | public override string GetString(byte[] bytes, int offset, int length, char spacingCharacter) | ||
| 352 | { | ||
| 353 | if ((object)bytes == null) | ||
| 354 | throw new ArgumentNullException("bytes", "Input buffer cannot be null"); | ||
| 355 | |||
| 356 | // Initializes byte image array on first call for speed in future calls. | ||
| 357 | if ((object)m_byteImages == null) | ||
| 358 | { | ||
| 359 | StringBuilder byteImage; | ||
| 360 | |||
| 361 | m_byteImages = new string[256]; | ||
| 362 | |||
| 363 | for (int imageByte = byte.MinValue; imageByte <= byte.MaxValue; imageByte++) | ||
| 364 | { | ||
| 365 | byteImage = new StringBuilder(); | ||
| 366 | |||
| 367 | if (m_reverse) | ||
| 368 | { | ||
| 369 | if (imageByte.CheckBits(Bits.Bit07)) | ||
| 370 | byteImage.Append('1'); | ||
| 371 | else | ||
| 372 | byteImage.Append('0'); | ||
| 373 | if (imageByte.CheckBits(Bits.Bit06)) | ||
| 374 | byteImage.Append('1'); | ||
| 375 | else | ||
| 376 | byteImage.Append('0'); | ||
| 377 | if (imageByte.CheckBits(Bits.Bit05)) | ||
| 378 | byteImage.Append('1'); | ||
| 379 | else | ||
| 380 | byteImage.Append('0'); | ||
| 381 | if (imageByte.CheckBits(Bits.Bit04)) | ||
| 382 | byteImage.Append('1'); | ||
| 383 | else | ||
| 384 | byteImage.Append('0'); | ||
| 385 | if (imageByte.CheckBits(Bits.Bit03)) | ||
| 386 | byteImage.Append('1'); | ||
| 387 | else | ||
| 388 | byteImage.Append('0'); | ||
| 389 | if (imageByte.CheckBits(Bits.Bit02)) | ||
| 390 | byteImage.Append('1'); | ||
| 391 | else | ||
| 392 | byteImage.Append('0'); | ||
| 393 | if (imageByte.CheckBits(Bits.Bit01)) | ||
| 394 | byteImage.Append('1'); | ||
| 395 | else | ||
| 396 | byteImage.Append('0'); | ||
| 397 | if (imageByte.CheckBits(Bits.Bit00)) | ||
| 398 | byteImage.Append('1'); | ||
| 399 | else | ||
| 400 | byteImage.Append('0'); | ||
| 401 | } | ||
| 402 | else | ||
| 403 | { | ||
| 404 | if (imageByte.CheckBits(Bits.Bit00)) | ||
| 405 | byteImage.Append('1'); | ||
| 406 | else | ||
| 407 | byteImage.Append('0'); | ||
| 408 | if (imageByte.CheckBits(Bits.Bit01)) | ||
| 409 | byteImage.Append('1'); | ||
| 410 | else | ||
| 411 | byteImage.Append('0'); | ||
| 412 | if (imageByte.CheckBits(Bits.Bit02)) | ||
| 413 | byteImage.Append('1'); | ||
| 414 | else | ||
| 415 | byteImage.Append('0'); | ||
| 416 | if (imageByte.CheckBits(Bits.Bit03)) | ||
| 417 | byteImage.Append('1'); | ||
| 418 | else | ||
| 419 | byteImage.Append('0'); | ||
| 420 | if (imageByte.CheckBits(Bits.Bit04)) | ||
| 421 | byteImage.Append('1'); | ||
| 422 | else | ||
| 423 | byteImage.Append('0'); | ||
| 424 | if (imageByte.CheckBits(Bits.Bit05)) | ||
| 425 | byteImage.Append('1'); | ||
| 426 | else | ||
| 427 | byteImage.Append('0'); | ||
| 428 | if (imageByte.CheckBits(Bits.Bit06)) | ||
| 429 | byteImage.Append('1'); | ||
| 430 | else | ||
| 431 | byteImage.Append('0'); | ||
| 432 | if (imageByte.CheckBits(Bits.Bit07)) | ||
| 433 | byteImage.Append('1'); | ||
| 434 | else | ||
| 435 | byteImage.Append('0'); | ||
| 436 | } | ||
| 437 | |||
| 438 | m_byteImages[imageByte] = byteImage.ToString(); | ||
| 439 | } | ||
| 440 | } | ||
| 441 | |||
| 442 | StringBuilder binaryImage = new StringBuilder(); | ||
| 443 | |||
| 444 | for (int x = 0; x < length; x++) | ||
| 445 | { | ||
| 446 | if (spacingCharacter != NoSpacing && x > 0) | ||
| 447 | binaryImage.Append(spacingCharacter); | ||
| 448 | binaryImage.Append(m_byteImages[bytes[offset + x]]); | ||
| 449 | } | ||
| 450 | |||
| 451 | return binaryImage.ToString(); | ||
| 452 | } | ||
| 453 | } | ||
| 454 | |||
| 455 | #endregion | ||
| 456 | |||
| 457 | #region [ Base64 Encoding Class ] | ||
| 458 | |||
| 459 | /// <summary> | ||
| 460 | /// Handles conversion of byte buffers to and from a base64 data format. | ||
| 461 | /// </summary> | ||
| 462 | [EditorBrowsable(EditorBrowsableState.Never)] | ||
| 463 | public class Base64Encoding : ByteEncoding | ||
| 464 | { | ||
| 465 | internal Base64Encoding() | ||
| 466 | { | ||
| 467 | // This class is meant for internal instantiation only. | ||
| 468 | } | ||
| 469 | |||
| 470 | /// <summary>Decodes given string back into a byte buffer.</summary> | ||
| 471 | /// <param name="binaryData">Encoded binary data string to decode.</param> | ||
| 472 | /// <param name="spacingCharacter">Original spacing character that was inserted between encoded bytes.</param> | ||
| 473 | /// <returns>Decoded bytes.</returns> | ||
| 474 | public override byte[] GetBytes(string binaryData, char spacingCharacter) | ||
| 475 | { | ||
| 476 | // Removes spacing characters, if needed. | ||
| 477 | binaryData = binaryData.Trim(); | ||
| 478 | if (spacingCharacter != NoSpacing) | ||
| 479 | binaryData = binaryData.Replace(spacingCharacter.ToString(), ""); | ||
| 480 | return Convert.FromBase64String(binaryData); | ||
| 481 | } | ||
| 482 | |||
| 483 | /// <summary>Encodes given buffer into a user presentable representation.</summary> | ||
| 484 | /// <param name="bytes">Bytes to encode.</param> | ||
| 485 | /// <param name="offset">Offset into buffer to begin encoding.</param> | ||
| 486 | /// <param name="length">Length of buffer to encode.</param> | ||
| 487 | /// <param name="spacingCharacter">Spacing character to place between encoded bytes.</param> | ||
| 488 | /// <returns>String of encoded bytes.</returns> | ||
| 489 | public override string GetString(byte[] bytes, int offset, int length, char spacingCharacter) | ||
| 490 | { | ||
| 491 | if ((object)bytes == null) | ||
| 492 | throw new ArgumentNullException("bytes", "Input buffer cannot be null"); | ||
| 493 | |||
| 494 | string base64String = Convert.ToBase64String(bytes, offset, length); | ||
| 495 | |||
| 496 | if (spacingCharacter == NoSpacing) | ||
| 497 | { | ||
| 498 | return base64String; | ||
| 499 | } | ||
| 500 | else | ||
| 501 | { | ||
| 502 | StringBuilder base64Image = new StringBuilder(); | ||
| 503 | |||
| 504 | for (int x = 0; x <= base64String.Length - 1; x++) | ||
| 505 | { | ||
| 506 | if (x > 0) | ||
| 507 | base64Image.Append(spacingCharacter); | ||
| 508 | base64Image.Append(base64String[x]); | ||
| 509 | } | ||
| 510 | |||
| 511 | return base64Image.ToString(); | ||
| 512 | } | ||
| 513 | } | ||
| 514 | } | ||
| 515 | |||
| 516 | #endregion | ||
| 517 | |||
| 518 | #region [ ASCII Encoding Class ] | ||
| 519 | |||
| 520 | /// <summary> | ||
| 521 | /// Handles conversion of byte buffers to and from a ASCII data format. | ||
| 522 | /// </summary> | ||
| 523 | [EditorBrowsable(EditorBrowsableState.Never)] | ||
| 524 | public class ASCIIEncoding : ByteEncoding | ||
| 525 | { | ||
| 526 | internal ASCIIEncoding() | ||
| 527 | { | ||
| 528 | // This class is meant for internal instantiation only. | ||
| 529 | } | ||
| 530 | |||
| 531 | /// <summary>Decodes given string back into a byte buffer.</summary> | ||
| 532 | /// <param name="binaryData">Encoded binary data string to decode.</param> | ||
| 533 | /// <param name="spacingCharacter">Original spacing character that was inserted between encoded bytes.</param> | ||
| 534 | /// <returns>Decoded bytes.</returns> | ||
| 535 | public override byte[] GetBytes(string binaryData, char spacingCharacter) | ||
| 536 | { | ||
| 537 | // Removes spacing characters, if needed. | ||
| 538 | binaryData = binaryData.Trim(); | ||
| 539 | if (spacingCharacter != NoSpacing) | ||
| 540 | binaryData = binaryData.Replace(spacingCharacter.ToString(), ""); | ||
| 541 | return Encoding.ASCII.GetBytes(binaryData); | ||
| 542 | } | ||
| 543 | |||
| 544 | /// <summary>Encodes given buffer into a user presentable representation.</summary> | ||
| 545 | /// <param name="bytes">Bytes to encode.</param> | ||
| 546 | /// <param name="offset">Offset into buffer to begin encoding.</param> | ||
| 547 | /// <param name="length">Length of buffer to encode.</param> | ||
| 548 | /// <param name="spacingCharacter">Spacing character to place between encoded bytes.</param> | ||
| 549 | /// <returns>String of encoded bytes.</returns> | ||
| 550 | public override string GetString(byte[] bytes, int offset, int length, char spacingCharacter) | ||
| 551 | { | ||
| 552 | if ((object)bytes == null) | ||
| 553 | throw new ArgumentNullException("bytes", "Input buffer cannot be null"); | ||
| 554 | |||
| 555 | string asciiString = Encoding.ASCII.GetString(bytes, offset, length); | ||
| 556 | |||
| 557 | if (spacingCharacter == NoSpacing) | ||
| 558 | { | ||
| 559 | return asciiString; | ||
| 560 | } | ||
| 561 | else | ||
| 562 | { | ||
| 563 | StringBuilder asciiImage = new StringBuilder(); | ||
| 564 | |||
| 565 | for (int x = 0; x <= asciiString.Length - 1; x++) | ||
| 566 | { | ||
| 567 | if (x > 0) | ||
| 568 | asciiImage.Append(spacingCharacter); | ||
| 569 | asciiImage.Append(asciiString[x]); | ||
| 570 | } | ||
| 571 | |||
| 572 | return asciiImage.ToString(); | ||
| 573 | } | ||
| 574 | } | ||
| 575 | } | ||
| 576 | |||
| 577 | #endregion | ||
| 578 | |||
| 579 | /// <summary> | ||
| 580 | /// Constant used to specify that "no spacing" should be used for data conversion. | ||
| 581 | /// </summary> | ||
| 582 | public const char NoSpacing = char.MinValue; | ||
| 583 | |||
| 584 | #endregion | ||
| 585 | |||
| 586 | #region [ Methods ] | ||
| 587 | |||
| 588 | /// <summary>Encodes given buffer into a user presentable representation.</summary> | ||
| 589 | /// <param name="bytes">Bytes to encode.</param> | ||
| 590 | /// <returns>String representation of byte array.</returns> | ||
| 591 | public virtual string GetString(byte[] bytes) | ||
| 592 | { | ||
| 593 | return GetString(bytes, NoSpacing); | ||
| 594 | } | ||
| 595 | |||
| 596 | /// <summary>Encodes given buffer into a user presentable representation.</summary> | ||
| 597 | /// <param name="bytes">Bytes to encode.</param> | ||
| 598 | /// <param name="spacingCharacter">Spacing character to place between encoded bytes.</param> | ||
| 599 | /// <returns>String of encoded bytes.</returns> | ||
| 600 | public virtual string GetString(byte[] bytes, char spacingCharacter) | ||
| 601 | { | ||
| 602 | if ((object)bytes == null) | ||
| 603 | throw new ArgumentNullException("bytes", "Input buffer cannot be null"); | ||
| 604 | |||
| 605 | return GetString(bytes, 0, bytes.Length, spacingCharacter); | ||
| 606 | } | ||
| 607 | |||
| 608 | /// <summary>Encodes given buffer into a user presentable representation.</summary> | ||
| 609 | /// <param name="bytes">Bytes to encode.</param> | ||
| 610 | /// <param name="offset">Offset into buffer to begin encoding.</param> | ||
| 611 | /// <param name="length">Length of buffer to encode.</param> | ||
| 612 | /// <returns>String of encoded bytes.</returns> | ||
| 613 | public virtual string GetString(byte[] bytes, int offset, int length) | ||
| 614 | { | ||
| 615 | if ((object)bytes == null) | ||
| 616 | throw new ArgumentNullException("bytes", "Input buffer cannot be null"); | ||
| 617 | |||
| 618 | return GetString(bytes, offset, length, NoSpacing); | ||
| 619 | } | ||
| 620 | |||
| 621 | /// <summary>Encodes given buffer into a user presentable representation.</summary> | ||
| 622 | /// <param name="bytes">Bytes to encode.</param> | ||
| 623 | /// <param name="offset">Offset into buffer to begin encoding.</param> | ||
| 624 | /// <param name="length">Length of buffer to encode.</param> | ||
| 625 | /// <param name="spacingCharacter">Spacing character to place between encoded bytes.</param> | ||
| 626 | /// <returns>String of encoded bytes.</returns> | ||
| 627 | public abstract string GetString(byte[] bytes, int offset, int length, char spacingCharacter); | ||
| 628 | |||
| 629 | /// <summary>Decodes given string back into a byte buffer.</summary> | ||
| 630 | /// <param name="value">Encoded string to decode.</param> | ||
| 631 | /// <returns>Decoded bytes.</returns> | ||
| 632 | public virtual byte[] GetBytes(string value) | ||
| 633 | { | ||
| 634 | if (string.IsNullOrEmpty(value)) | ||
| 635 | throw new ArgumentNullException("value", "Input string cannot be null"); | ||
| 636 | return GetBytes(value, NoSpacing); | ||
| 637 | } | ||
| 638 | |||
| 639 | /// <summary>Decodes given string back into a byte buffer.</summary> | ||
| 640 | /// <param name="value">Encoded string to decode.</param> | ||
| 641 | /// <param name="spacingCharacter">Original spacing character that was inserted between encoded bytes.</param> | ||
| 642 | /// <returns>Decoded bytes</returns> | ||
| 643 | public abstract byte[] GetBytes(string value, char spacingCharacter); | ||
| 644 | |||
| 645 | #endregion | ||
| 646 | |||
| 647 | #region [ Static ] | ||
| 648 | |||
| 649 | // Static Fields | ||
| 650 | private static ByteEncoding s_hexadecimalEncoding; | ||
| 651 | private static ByteEncoding s_decimalEncoding; | ||
| 652 | private static ByteEncoding s_bigEndianBinaryEncoding; | ||
| 653 | private static ByteEncoding s_littleEndianBinaryEncoding; | ||
| 654 | private static ByteEncoding s_base64Encoding; | ||
| 655 | private static ByteEncoding s_asciiEncoding; | ||
| 656 | |||
| 657 | /// <summary>Handles encoding and decoding of a byte buffer into a hexadecimal-based presentation format.</summary> | ||
| 658 | public static ByteEncoding Hexadecimal | ||
| 659 | { | ||
| 660 | get | ||
| 661 | { | ||
| 662 | if ((object)s_hexadecimalEncoding == null) | ||
| 663 | s_hexadecimalEncoding = new HexadecimalEncoding(); | ||
| 664 | |||
| 665 | return s_hexadecimalEncoding; | ||
| 666 | } | ||
| 667 | } | ||
| 668 | |||
| 669 | /// <summary>Handles encoding and decoding of a byte buffer into an integer-based presentation format.</summary> | ||
| 670 | public static ByteEncoding Decimal | ||
| 671 | { | ||
| 672 | get | ||
| 673 | { | ||
| 674 | if ((object)s_decimalEncoding == null) | ||
| 675 | s_decimalEncoding = new DecimalEncoding(); | ||
| 676 | |||
| 677 | return s_decimalEncoding; | ||
| 678 | } | ||
| 679 | } | ||
| 680 | |||
| 681 | /// <summary>Handles encoding and decoding of a byte buffer into a big-endian binary (i.e., 0 and 1's) based | ||
| 682 | /// presentation format.</summary> | ||
| 683 | /// <remarks> | ||
| 684 | /// Although endianness is typically used in the context of byte order (see <see cref="GSF.EndianOrder"/> to handle byte | ||
| 685 | /// order swapping), this property allows you visualize "bits" in big-endian order, right-to-left. Note that bits are | ||
| 686 | /// normally stored in the same order as their bytes.). | ||
| 687 | /// </remarks> | ||
| 688 | public static ByteEncoding BigEndianBinary | ||
| 689 | { | ||
| 690 | get | ||
| 691 | { | ||
| 692 | if ((object)s_bigEndianBinaryEncoding == null) | ||
| 693 | s_bigEndianBinaryEncoding = new BinaryEncoding(Endianness.BigEndian); | ||
| 694 | |||
| 695 | return s_bigEndianBinaryEncoding; | ||
| 696 | } | ||
| 697 | } | ||
| 698 | |||
| 699 | /// <summary>Handles encoding and decoding of a byte buffer into a little-endian binary (i.e., 0 and 1's) based | ||
| 700 | /// presentation format.</summary> | ||
| 701 | /// <remarks> | ||
| 702 | /// Although endianness is typically used in the context of byte order (see <see cref="GSF.EndianOrder"/> to handle byte | ||
| 703 | /// order swapping), this property allows you visualize "bits" in little-endian order, left-to-right. Note that bits are | ||
| 704 | /// normally stored in the same order as their bytes. | ||
| 705 | /// </remarks> | ||
| 706 | public static ByteEncoding LittleEndianBinary | ||
| 707 | { | ||
| 708 | get | ||
| 709 | { | ||
| 710 | if ((object)s_littleEndianBinaryEncoding == null) | ||
| 711 | s_littleEndianBinaryEncoding = new BinaryEncoding(Endianness.LittleEndian); | ||
| 712 | |||
| 713 | return s_littleEndianBinaryEncoding; | ||
| 714 | } | ||
| 715 | } | ||
| 716 | |||
| 717 | /// <summary>Handles encoding and decoding of a byte buffer into a base64 presentation format.</summary> | ||
| 718 | public static ByteEncoding Base64 | ||
| 719 | { | ||
| 720 | get | ||
| 721 | { | ||
| 722 | if ((object)s_base64Encoding == null) | ||
| 723 | s_base64Encoding = new Base64Encoding(); | ||
| 724 | |||
| 725 | return s_base64Encoding; | ||
| 726 | } | ||
| 727 | } | ||
| 728 | |||
| 729 | /// <summary>Handles encoding and decoding of a byte buffer into an ASCII character presentation format.</summary> | ||
| 730 | public static ByteEncoding ASCII | ||
| 731 | { | ||
| 732 | get | ||
| 733 | { | ||
| 734 | if ((object)s_asciiEncoding == null) | ||
| 735 | s_asciiEncoding = new ASCIIEncoding(); | ||
| 736 | |||
| 737 | return s_asciiEncoding; | ||
| 738 | } | ||
| 739 | } | ||
| 740 | |||
| 741 | /// <summary>Handles byte to string conversions for implementations that are available from Byte.ToString.</summary> | ||
| 742 | /// <param name="bytes">Encoded string to decode.</param> | ||
| 743 | /// <param name="offset">Offset into byte array to begin decoding straing at.</param> | ||
| 744 | /// <param name="length">Number of bytes to decode starting at <paramref name="offset"/></param> | ||
| 745 | /// <param name="spacingCharacter">Character to insert between each byte</param> | ||
| 746 | /// <param name="format">String decoding format.</param> | ||
| 747 | /// <returns>Decoded string</returns> | ||
| 748 | internal static string BytesToString(byte[] bytes, int offset, int length, char spacingCharacter, string format) | ||
| 749 | { | ||
| 750 | if ((object)bytes == null) | ||
| 751 | throw new ArgumentNullException("bytes", "Input buffer cannot be null"); | ||
| 752 | |||
| 753 | StringBuilder byteString = new StringBuilder(); | ||
| 754 | |||
| 755 | for (int x = 0; x <= length - 1; x++) | ||
| 756 | { | ||
| 757 | if (spacingCharacter != NoSpacing && x > 0) | ||
| 758 | byteString.Append(spacingCharacter); | ||
| 759 | byteString.Append(bytes[x + offset].ToString(format)); | ||
| 760 | } | ||
| 761 | |||
| 762 | return byteString.ToString(); | ||
| 763 | } | ||
| 764 | |||
| 765 | #endregion | ||
| 766 | } | ||
| 767 | } | ||