TarExtendedHeaderReader.cs 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. using System.Collections.Generic;
  2. using System.Text;
  3. namespace ICSharpCode.SharpZipLib.Tar
  4. {
  5. /// <summary>
  6. /// Reads the extended header of a Tar stream
  7. /// </summary>
  8. public class TarExtendedHeaderReader
  9. {
  10. private const byte LENGTH = 0;
  11. private const byte KEY = 1;
  12. private const byte VALUE = 2;
  13. private const byte END = 3;
  14. private readonly Dictionary<string, string> headers = new Dictionary<string, string>();
  15. private string[] headerParts = new string[3];
  16. private int bbIndex;
  17. private byte[] byteBuffer;
  18. private char[] charBuffer;
  19. private readonly StringBuilder sb = new StringBuilder();
  20. private readonly Decoder decoder = Encoding.UTF8.GetDecoder();
  21. private int state = LENGTH;
  22. private static readonly byte[] StateNext = new[] { (byte)' ', (byte)'=', (byte)'\n' };
  23. /// <summary>
  24. /// Creates a new <see cref="TarExtendedHeaderReader"/>.
  25. /// </summary>
  26. public TarExtendedHeaderReader()
  27. {
  28. ResetBuffers();
  29. }
  30. /// <summary>
  31. /// Read <paramref name="length"/> bytes from <paramref name="buffer"/>
  32. /// </summary>
  33. /// <param name="buffer"></param>
  34. /// <param name="length"></param>
  35. public void Read(byte[] buffer, int length)
  36. {
  37. for (int i = 0; i < length; i++)
  38. {
  39. byte next = buffer[i];
  40. if (next == StateNext[state])
  41. {
  42. Flush();
  43. headerParts[state] = sb.ToString();
  44. sb.Clear();
  45. if (++state == END)
  46. {
  47. headers.Add(headerParts[KEY], headerParts[VALUE]);
  48. headerParts = new string[3];
  49. state = LENGTH;
  50. }
  51. }
  52. else
  53. {
  54. byteBuffer[bbIndex++] = next;
  55. if (bbIndex == 4)
  56. Flush();
  57. }
  58. }
  59. }
  60. private void Flush()
  61. {
  62. decoder.Convert(byteBuffer, 0, bbIndex, charBuffer, 0, 4, false, out int bytesUsed, out int charsUsed, out bool completed);
  63. sb.Append(charBuffer, 0, charsUsed);
  64. ResetBuffers();
  65. }
  66. private void ResetBuffers()
  67. {
  68. charBuffer = new char[4];
  69. byteBuffer = new byte[4];
  70. bbIndex = 0;
  71. }
  72. /// <summary>
  73. /// Returns the parsed headers as key-value strings
  74. /// </summary>
  75. public Dictionary<string, string> Headers
  76. {
  77. get
  78. {
  79. // TODO: Check for invalid state? -NM 2018-07-01
  80. return headers;
  81. }
  82. }
  83. }
  84. }