FF8String.cs 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. using System;
  2. using System.Collections;
  3. using System.Linq;
  4. namespace OpenVIII
  5. {
  6. /// <summary>
  7. /// This holds the encoded bytes and provides implict casts to string and byte[]
  8. /// </summary>
  9. public class FF8String : IEnumerator, IEnumerable
  10. {
  11. #region Fields
  12. protected byte[] value;
  13. private static Encoding.FF8TextEncoding encoding = new Encoding.FF8TextEncoding(Encoding.FF8TextEncodingCodepage.Create());
  14. private int position = 0;
  15. #endregion Fields
  16. #region Constructors
  17. public FF8String()
  18. {
  19. }
  20. public FF8String(byte[] @value) => this.value = @value;
  21. public FF8String(string @value) => this.value = @value != null ? encoding.GetBytes(@value) : null;
  22. #endregion Constructors
  23. #region Properties
  24. public object Current => Value[position - 1];
  25. public virtual byte[] Value { get => value; set => this.value = value; }
  26. /// <summary>
  27. /// This is incorrect as null can be in the beginning of strings as a marker or tag.
  28. /// But I can't figure out how to make his code leave null as null.
  29. /// </summary>
  30. public string Value_str => encoding.GetString(Value ?? new byte[] { }).TrimEnd('\0').Replace("{End}", "");
  31. public virtual int Length => value == null ? 0 : value.Length;
  32. #endregion Properties
  33. #region Indexers
  34. public byte this[int index] => value[index];
  35. #endregion Indexers
  36. #region Methods
  37. public static FF8String Combine(FF8String start, FF8String end)
  38. {
  39. if (end != null && end.Length > 0)
  40. {
  41. var combine = new byte[start.Length + end.Length];
  42. Array.Copy(start, 0, combine, 0, start.Length);
  43. Array.Copy(end, 0, combine, start.Length, end.Length);
  44. return combine;
  45. }
  46. else
  47. return start;
  48. }
  49. public static implicit operator byte[] (FF8String input) => input?.Value;
  50. public static implicit operator FF8String(string input) => new FF8String(input);
  51. public static implicit operator FF8String(byte[] input) => new FF8String(input);
  52. public static implicit operator string(FF8String input) => input?.Value_str;
  53. public static FF8String operator +(FF8String a, FF8String b)
  54. {
  55. if (a != null && a.Length > 0)
  56. {
  57. var s = a.Clone();
  58. if (b != null && b.Length > 0)
  59. return s.Append(b);
  60. else
  61. return a;
  62. }
  63. return b;
  64. }
  65. public static FF8String operator +(FF8String a, string b)
  66. {
  67. if (a != null && a.Length > 0)
  68. {
  69. if (!string.IsNullOrEmpty(b))
  70. {
  71. var s = a.Clone();
  72. return s.Append(b);
  73. }
  74. else
  75. return a;
  76. }
  77. return b;
  78. }
  79. public static FF8String operator +(string a, FF8String b)
  80. {
  81. var s = new FF8String(a);
  82. return s.Append(b);
  83. }
  84. public FF8String Append(FF8String end)
  85. {
  86. if (Value != null && Value.Length > 0)
  87. {
  88. if (end != null && end.Length > 0)
  89. {
  90. Array.Resize(ref value, Length + end.Length);
  91. Array.Copy(end.Value, 0, value, Length - end.Length, end.Length);
  92. }
  93. }
  94. else
  95. {
  96. if (end != null && end.Length > 0)
  97. {
  98. Value = end;
  99. }
  100. }
  101. return this;
  102. }
  103. public FF8String Clone()
  104. {
  105. if (Length > 0)
  106. return new FF8String
  107. {
  108. value = (byte[])(value.Clone())
  109. };
  110. else return new FF8String();
  111. }
  112. public FF8String Replace(FF8String a, FF8String b)
  113. {
  114. if (Length > 0 && a != null && b != null && a.Length > 0 && b.Length > 0)
  115. {
  116. var i = 0;
  117. do
  118. {
  119. i = Array.FindIndex(value, i, Length - i, x => x == a[0]);
  120. if (i >= 0)
  121. {
  122. if (value.Skip(i).Take(a.Length).ToArray().SequenceEqual(a.Value))
  123. {
  124. var end = value.Skip(a.Length + i).ToArray();
  125. Array.Resize(ref value, Length + b.Length - a.Length);
  126. Array.Copy(b, 0, value, i, b.Length);
  127. Array.Copy(end, 0, value, i + b.Length, end.Length);
  128. i += b.Length;
  129. }
  130. else
  131. {
  132. i++;
  133. }
  134. }
  135. else break;
  136. }
  137. while (i < Length);
  138. }
  139. return this;
  140. }
  141. public IEnumerator GetEnumerator()
  142. {
  143. if (Value != null && Value.Length > 0)
  144. return this;
  145. return null;
  146. }
  147. public bool MoveNext()
  148. {
  149. if (++position <= Length)
  150. return true;
  151. else
  152. {
  153. Reset();
  154. return false;
  155. }
  156. }
  157. public void Reset() => position = 0;
  158. public override string ToString() => Value_str;
  159. #endregion Methods
  160. }
  161. }