BinaryUtil.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Collections;
  6. namespace SuperSocket.Common
  7. {
  8. /// <summary>
  9. /// Binary util class
  10. /// </summary>
  11. public static class BinaryUtil
  12. {
  13. /// <summary>
  14. /// Search target from source.
  15. /// </summary>
  16. /// <typeparam name="T"></typeparam>
  17. /// <param name="source">The source.</param>
  18. /// <param name="target">The target.</param>
  19. /// <param name="pos">The pos.</param>
  20. /// <param name="length">The length.</param>
  21. /// <returns></returns>
  22. public static int IndexOf<T>(this IList<T> source, T target, int pos, int length)
  23. where T : IEquatable<T>
  24. {
  25. for (int i = pos; i < pos + length; i++)
  26. {
  27. if (source[i].Equals(target))
  28. return i;
  29. }
  30. return -1;
  31. }
  32. /// <summary>
  33. /// Searches the mark from source.
  34. /// </summary>
  35. /// <typeparam name="T"></typeparam>
  36. /// <param name="source">The source.</param>
  37. /// <param name="mark">The mark.</param>
  38. /// <param name="parsedLength">Length of the parsed.</param>
  39. /// <returns></returns>
  40. public static int? SearchMark<T>(this IList<T> source, T[] mark, out int parsedLength)
  41. where T : IEquatable<T>
  42. {
  43. return SearchMark(source, 0, source.Count, mark, 0, out parsedLength);
  44. }
  45. /// <summary>
  46. /// Searches the mark from source.
  47. /// </summary>
  48. /// <typeparam name="T"></typeparam>
  49. /// <param name="source">The source.</param>
  50. /// <param name="mark">The mark.</param>
  51. /// <returns></returns>
  52. public static int? SearchMark<T>(this IList<T> source, T[] mark)
  53. where T : IEquatable<T>
  54. {
  55. int parsedLength;
  56. return SearchMark(source, 0, source.Count, mark, 0, out parsedLength);
  57. }
  58. /// <summary>
  59. /// Searches the mark from source.
  60. /// </summary>
  61. /// <typeparam name="T"></typeparam>
  62. /// <param name="source">The source.</param>
  63. /// <param name="offset">The offset.</param>
  64. /// <param name="length">The length.</param>
  65. /// <param name="mark">The mark.</param>
  66. /// <returns></returns>
  67. public static int? SearchMark<T>(this IList<T> source, int offset, int length, T[] mark)
  68. where T : IEquatable<T>
  69. {
  70. int parsedLength;
  71. return SearchMark(source, offset, length, mark, 0, out parsedLength);
  72. }
  73. /// <summary>
  74. /// Searches the mark from source.
  75. /// </summary>
  76. /// <typeparam name="T"></typeparam>
  77. /// <param name="source">The source.</param>
  78. /// <param name="offset">The offset.</param>
  79. /// <param name="length">The length.</param>
  80. /// <param name="mark">The mark.</param>
  81. /// <param name="parsedLength">Length of the parsed.</param>
  82. /// <returns></returns>
  83. public static int? SearchMark<T>(this IList<T> source, int offset, int length, T[] mark, out int parsedLength)
  84. where T : IEquatable<T>
  85. {
  86. return SearchMark(source, offset, length, mark, 0, out parsedLength);
  87. }
  88. /// <summary>
  89. /// Searches the mark from source.
  90. /// </summary>
  91. /// <typeparam name="T"></typeparam>
  92. /// <param name="source">The source.</param>
  93. /// <param name="offset">The offset.</param>
  94. /// <param name="length">The length.</param>
  95. /// <param name="mark">The mark.</param>
  96. /// <param name="matched">The matched.</param>
  97. /// <returns></returns>
  98. public static int? SearchMark<T>(this IList<T> source, int offset, int length, T[] mark, int matched)
  99. where T : IEquatable<T>
  100. {
  101. int parsedLength;
  102. return source.SearchMark(offset, length, mark, matched, out parsedLength);
  103. }
  104. /// <summary>
  105. /// Searches the mark from source.
  106. /// </summary>
  107. /// <typeparam name="T"></typeparam>
  108. /// <param name="source">The source.</param>
  109. /// <param name="offset">The offset.</param>
  110. /// <param name="length">The length.</param>
  111. /// <param name="mark">The mark.</param>
  112. /// <param name="matched">The matched.</param>
  113. /// <param name="parsedLength">Length of the parsed.</param>
  114. /// <returns></returns>
  115. public static int? SearchMark<T>(this IList<T> source, int offset, int length, T[] mark, int matched, out int parsedLength)
  116. where T : IEquatable<T>
  117. {
  118. int pos = offset;
  119. int endOffset = offset + length - 1;
  120. int matchCount = matched;
  121. parsedLength = 0;
  122. if (matched > 0)
  123. {
  124. for (int i = matchCount; i < mark.Length; i++)
  125. {
  126. if (!source[pos++].Equals(mark[i]))
  127. break;
  128. matchCount++;
  129. if (pos > endOffset)
  130. {
  131. if (matchCount == mark.Length)
  132. {
  133. parsedLength = mark.Length - matched;
  134. return offset;
  135. }
  136. else
  137. {
  138. return (0 - matchCount);
  139. }
  140. }
  141. }
  142. if (matchCount == mark.Length)
  143. {
  144. parsedLength = mark.Length - matched;
  145. return offset;
  146. }
  147. pos = offset;
  148. matchCount = 0;
  149. }
  150. while (true)
  151. {
  152. pos = source.IndexOf(mark[matchCount], pos, length - pos + offset);
  153. if (pos < 0)
  154. return null;
  155. matchCount += 1;
  156. for (int i = matchCount; i < mark.Length; i++)
  157. {
  158. int checkPos = pos + i;
  159. if (checkPos > endOffset)
  160. {
  161. //found end, return matched chars count
  162. return (0 - matchCount);
  163. }
  164. if (!source[checkPos].Equals(mark[i]))
  165. break;
  166. matchCount++;
  167. }
  168. //found the full end mark
  169. if (matchCount == mark.Length)
  170. {
  171. parsedLength = pos - offset + mark.Length;
  172. return pos;
  173. }
  174. //Reset next round read pos
  175. pos += 1;
  176. //clear matched chars count
  177. matchCount = 0;
  178. }
  179. }
  180. /// <summary>
  181. /// Searches the mark from source.
  182. /// </summary>
  183. /// <typeparam name="T"></typeparam>
  184. /// <param name="source">The source.</param>
  185. /// <param name="offset">The offset.</param>
  186. /// <param name="length">The length.</param>
  187. /// <param name="searchState">State of the search.</param>
  188. /// <param name="parsedLength">Length of the parsed.</param>
  189. /// <returns></returns>
  190. public static int SearchMark<T>(this IList<T> source, int offset, int length, SearchMarkState<T> searchState, out int parsedLength)
  191. where T : IEquatable<T>
  192. {
  193. int? result = source.SearchMark(offset, length, searchState.Mark, searchState.Matched, out parsedLength);
  194. if (!result.HasValue)
  195. {
  196. searchState.Matched = 0;
  197. return -1;
  198. }
  199. if (result.Value < 0)
  200. {
  201. searchState.Matched = 0 - result.Value;
  202. return -1;
  203. }
  204. searchState.Matched = 0;
  205. return result.Value;
  206. }
  207. /// <summary>
  208. /// Searches the mark from source.
  209. /// </summary>
  210. /// <typeparam name="T"></typeparam>
  211. /// <param name="source">The source.</param>
  212. /// <param name="offset">The offset.</param>
  213. /// <param name="length">The length.</param>
  214. /// <param name="searchState">State of the search.</param>
  215. /// <returns></returns>
  216. public static int SearchMark<T>(this IList<T> source, int offset, int length, SearchMarkState<T> searchState)
  217. where T : IEquatable<T>
  218. {
  219. var parsedLen = 0;
  220. return SearchMark(source, offset, length, searchState, out parsedLen);
  221. }
  222. /// <summary>
  223. /// Startses the with.
  224. /// </summary>
  225. /// <typeparam name="T"></typeparam>
  226. /// <param name="source">The source.</param>
  227. /// <param name="mark">The mark.</param>
  228. /// <returns></returns>
  229. public static int StartsWith<T>(this IList<T> source, T[] mark)
  230. where T : IEquatable<T>
  231. {
  232. return source.StartsWith(0, source.Count, mark);
  233. }
  234. /// <summary>
  235. /// Startses the with.
  236. /// </summary>
  237. /// <typeparam name="T"></typeparam>
  238. /// <param name="source">The source.</param>
  239. /// <param name="offset">The offset.</param>
  240. /// <param name="length">The length.</param>
  241. /// <param name="mark">The mark.</param>
  242. /// <returns></returns>
  243. public static int StartsWith<T>(this IList<T> source, int offset, int length, T[] mark)
  244. where T : IEquatable<T>
  245. {
  246. int pos = offset;
  247. int endOffset = offset + length - 1;
  248. for (int i = 0; i < mark.Length; i++)
  249. {
  250. int checkPos = pos + i;
  251. if (checkPos > endOffset)
  252. return i;
  253. if (!source[checkPos].Equals(mark[i]))
  254. return -1;
  255. }
  256. return mark.Length;
  257. }
  258. /// <summary>
  259. /// Endses the with.
  260. /// </summary>
  261. /// <typeparam name="T"></typeparam>
  262. /// <param name="source">The source.</param>
  263. /// <param name="mark">The mark.</param>
  264. /// <returns></returns>
  265. public static bool EndsWith<T>(this IList<T> source, T[] mark)
  266. where T : IEquatable<T>
  267. {
  268. return source.EndsWith(0, source.Count, mark);
  269. }
  270. /// <summary>
  271. /// Endses the with.
  272. /// </summary>
  273. /// <typeparam name="T"></typeparam>
  274. /// <param name="source">The source.</param>
  275. /// <param name="offset">The offset.</param>
  276. /// <param name="length">The length.</param>
  277. /// <param name="mark">The mark.</param>
  278. /// <returns></returns>
  279. public static bool EndsWith<T>(this IList<T> source, int offset, int length, T[] mark)
  280. where T : IEquatable<T>
  281. {
  282. if (mark.Length > length)
  283. return false;
  284. for (int i = 0; i < Math.Min(length, mark.Length); i++)
  285. {
  286. if (!mark[i].Equals(source[offset + length - mark.Length + i]))
  287. return false;
  288. }
  289. return true;
  290. }
  291. /// <summary>
  292. /// Clones the elements in the specific range.
  293. /// </summary>
  294. /// <typeparam name="T"></typeparam>
  295. /// <param name="source">The source.</param>
  296. /// <param name="offset">The offset.</param>
  297. /// <param name="length">The length.</param>
  298. /// <returns></returns>
  299. public static T[] CloneRange<T>(this IList<T> source, int offset, int length)
  300. {
  301. T[] target;
  302. var array = source as T[];
  303. if (array != null)
  304. {
  305. target = new T[length];
  306. Array.Copy(array, offset, target, 0, length);
  307. return target;
  308. }
  309. target = new T[length];
  310. for (int i = 0; i < length; i++)
  311. {
  312. target[i] = source[offset + i];
  313. }
  314. return target;
  315. }
  316. }
  317. }