Substring.cs 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. using System;
  2. namespace UnityEngine.InputSystem.Utilities
  3. {
  4. // Work with substrings without actually allocating strings.
  5. internal struct Substring : IComparable<Substring>, IEquatable<Substring>
  6. {
  7. private readonly string m_String;
  8. private readonly int m_Index;
  9. private readonly int m_Length;
  10. public bool isEmpty => m_Length == 0;
  11. public Substring(string str)
  12. {
  13. m_String = str;
  14. m_Index = 0;
  15. if (str != null)
  16. m_Length = str.Length;
  17. else
  18. m_Length = 0;
  19. }
  20. public Substring(string str, int index, int length)
  21. {
  22. Debug.Assert(str == null || index < str.Length);
  23. Debug.Assert(str != null || length == 0);
  24. m_String = str;
  25. m_Index = index;
  26. m_Length = length;
  27. }
  28. public Substring(string str, int index)
  29. {
  30. Debug.Assert(str == null || index < str.Length);
  31. m_String = str;
  32. m_Index = index;
  33. m_Length = str.Length - index;
  34. }
  35. public override bool Equals(object obj)
  36. {
  37. if (obj is Substring other)
  38. return Equals(other);
  39. if (obj is string str)
  40. return Equals(str);
  41. return false;
  42. }
  43. public bool Equals(string other)
  44. {
  45. if (string.IsNullOrEmpty(other))
  46. return m_Length == 0;
  47. if (other.Length != m_Length)
  48. return false;
  49. for (var i = 0; i < m_Length; ++i)
  50. if (other[i] != m_String[m_Index + i])
  51. return false;
  52. return true;
  53. }
  54. public bool Equals(Substring other)
  55. {
  56. return CompareTo(other) == 0;
  57. }
  58. public bool Equals(InternedString other)
  59. {
  60. if (length != other.length)
  61. return false;
  62. return string.Compare(m_String, m_Index, other.ToString(), 0, length,
  63. StringComparison.OrdinalIgnoreCase) == 0;
  64. }
  65. public int CompareTo(Substring other)
  66. {
  67. return Compare(this, other, StringComparison.CurrentCulture);
  68. }
  69. public static int Compare(Substring left, Substring right, StringComparison comparison)
  70. {
  71. if (left.m_Length != right.m_Length)
  72. {
  73. if (left.m_Length < right.m_Length)
  74. return -1;
  75. return 1;
  76. }
  77. return string.Compare(left.m_String, left.m_Index, right.m_String, right.m_Index, left.m_Length,
  78. comparison);
  79. }
  80. public bool StartsWith(string str)
  81. {
  82. if (str.Length > length)
  83. return false;
  84. for (var i = 0; i < str.Length; ++i)
  85. if (m_String[m_Index + i] != str[i])
  86. return false;
  87. return true;
  88. }
  89. public string Substr(int index = 0, int length = -1)
  90. {
  91. if (length < 0)
  92. length = this.length - index;
  93. return m_String.Substring(m_Index + index, length);
  94. }
  95. public override string ToString()
  96. {
  97. if (m_String == null)
  98. return string.Empty;
  99. return m_String.Substring(m_Index, m_Length);
  100. }
  101. public override int GetHashCode()
  102. {
  103. if (m_String == null)
  104. return 0;
  105. if (m_Index == 0 && m_Length == m_String.Length)
  106. return m_String.GetHashCode();
  107. ////FIXME: this is bad... shouldn't allocate
  108. return ToString().GetHashCode();
  109. }
  110. public static bool operator==(Substring a, Substring b)
  111. {
  112. return a.Equals(b);
  113. }
  114. public static bool operator!=(Substring a, Substring b)
  115. {
  116. return !a.Equals(b);
  117. }
  118. public static bool operator==(Substring a, InternedString b)
  119. {
  120. return a.Equals(b);
  121. }
  122. public static bool operator!=(Substring a, InternedString b)
  123. {
  124. return !a.Equals(b);
  125. }
  126. public static bool operator==(InternedString a, Substring b)
  127. {
  128. return b.Equals(a);
  129. }
  130. public static bool operator!=(InternedString a, Substring b)
  131. {
  132. return !b.Equals(a);
  133. }
  134. public static implicit operator Substring(string s)
  135. {
  136. return new Substring(s);
  137. }
  138. public int length => m_Length;
  139. public int index => m_Index;
  140. public char this[int index]
  141. {
  142. get
  143. {
  144. if (index < 0 || index >= m_Length)
  145. throw new ArgumentOutOfRangeException(nameof(index));
  146. return m_String[m_Index + index];
  147. }
  148. }
  149. }
  150. }