NIO.Buffer.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Linq;
  5. using System.Text;
  6. namespace CommonLang.NIO
  7. {
  8. public enum ByteOrder
  9. {
  10. LITTLE_ENDIAN,
  11. BIG_ENDIAN,
  12. }
  13. public abstract class Buffer
  14. {
  15. // Invariants: mark <= position <= limit <= capacity
  16. private int mark = -1;
  17. private int position = 0;
  18. private int limit;
  19. private int capacity;
  20. // Used only by direct buffers
  21. // NOTE: hoisted here for speed in JNI GetDirectBufferAddress
  22. //IntPtr address;
  23. // Creates a new buffer with the given mark, position, limit, and capacity,
  24. // after checking invariants.
  25. //
  26. internal Buffer(int mark, int pos, int lim, int cap)
  27. {
  28. if (cap < 0)
  29. throw new Exception("Negative capacity: " + cap);
  30. this.capacity = cap;
  31. Limit(lim);
  32. Position(pos);
  33. if (mark >= 0)
  34. {
  35. if (mark > pos)
  36. throw new Exception("mark > position: ("
  37. + mark + " > " + pos + ")");
  38. this.mark = mark;
  39. }
  40. }
  41. public int Capacity()
  42. {
  43. return capacity;
  44. }
  45. public int Position()
  46. {
  47. return position;
  48. }
  49. public Buffer Position(int newPosition)
  50. {
  51. if ((newPosition > limit) || (newPosition < 0))
  52. throw new Exception("IllegalArgumentException");
  53. position = newPosition;
  54. if (mark > position) mark = -1;
  55. return this;
  56. }
  57. public int Limit()
  58. {
  59. return limit;
  60. }
  61. public Buffer Limit(int newLimit)
  62. {
  63. if ((newLimit > capacity) || (newLimit < 0))
  64. throw new Exception("IllegalArgumentException");
  65. limit = newLimit;
  66. if (position > limit) position = limit;
  67. if (mark > limit) mark = -1;
  68. return this;
  69. }
  70. public Buffer Mark()
  71. {
  72. mark = position;
  73. return this;
  74. }
  75. public Buffer Reset()
  76. {
  77. int m = mark;
  78. if (m < 0)
  79. throw new Exception("InvalidMarkException");
  80. position = m;
  81. return this;
  82. }
  83. public Buffer Clear()
  84. {
  85. position = 0;
  86. limit = capacity;
  87. mark = -1;
  88. return this;
  89. }
  90. public Buffer Flip()
  91. {
  92. limit = position;
  93. position = 0;
  94. mark = -1;
  95. return this;
  96. }
  97. public Buffer Rewind()
  98. {
  99. position = 0;
  100. mark = -1;
  101. return this;
  102. }
  103. public int Remaining()
  104. {
  105. return limit - position;
  106. }
  107. public bool HasRemaining()
  108. {
  109. return position < limit;
  110. }
  111. public abstract bool IsReadOnly();
  112. public abstract bool HasArray();
  113. public abstract Array Array();
  114. public abstract int ArrayOffset();
  115. internal int NextGetIndex()
  116. {
  117. if (position >= limit)
  118. throw new Exception("BufferUnderflowException");
  119. return position++;
  120. }
  121. internal int NextGetIndex(int nb)
  122. {
  123. if (limit - position < nb)
  124. throw new Exception("BufferUnderflowException");
  125. int p = position;
  126. position += nb;
  127. return p;
  128. }
  129. internal int NextPutIndex()
  130. {
  131. if (position >= limit)
  132. throw new Exception("BufferOverflowException");
  133. return position++;
  134. }
  135. internal int NextPutIndex(int nb)
  136. {
  137. if (limit - position < nb)
  138. throw new Exception("BufferOverflowException");
  139. int p = position;
  140. position += nb;
  141. return p;
  142. }
  143. internal int CheckIndex(int i)
  144. {
  145. if ((i < 0) || (i >= limit))
  146. throw new IndexOutOfRangeException();
  147. return i;
  148. }
  149. internal int CheckIndex(int i, int nb)
  150. {
  151. if ((i < 0) || (nb > limit - i))
  152. throw new IndexOutOfRangeException();
  153. return i;
  154. }
  155. internal int MarkValue()
  156. {
  157. return mark;
  158. }
  159. internal void Truncate()
  160. {
  161. mark = -1;
  162. position = 0;
  163. limit = 0;
  164. capacity = 0;
  165. }
  166. internal void DiscardMark()
  167. {
  168. mark = -1;
  169. }
  170. internal static void CheckBounds(int off, int len, int size)
  171. {
  172. if ((off | len | (off + len) | (size - (off + len))) < 0)
  173. throw new IndexOutOfRangeException();
  174. }
  175. }
  176. public abstract class ByteBuffer : Buffer
  177. {
  178. readonly internal byte[] hb;
  179. readonly internal int offset;
  180. internal ByteBuffer(int mark, int pos, int lim, int cap,
  181. byte[] hb, int offset)
  182. : base(mark, pos, lim, cap)
  183. {
  184. this.hb = hb;
  185. this.offset = offset;
  186. }
  187. internal ByteBuffer(int mark, int pos, int lim, int cap)
  188. : this(mark, pos, lim, cap, null, 0)
  189. {
  190. }
  191. public static ByteBuffer Allocate(int capacity)
  192. {
  193. if (capacity < 0)
  194. throw new Exception("IllegalArgumentException");
  195. return new HeapByteBuffer(capacity, capacity);
  196. }
  197. public static ByteBuffer Wrap(byte[] array, int offset, int length)
  198. {
  199. try
  200. {
  201. return new HeapByteBuffer(array, offset, length);
  202. }
  203. catch (Exception err)
  204. {
  205. Console.WriteLine("Wrap 1: " + array + ", catch: " + err);
  206. throw new IndexOutOfRangeException();
  207. }
  208. }
  209. public static ByteBuffer Wrap(byte[] array)
  210. {
  211. return Wrap(array, 0, array.Length);
  212. }
  213. public abstract ByteBuffer Slice();
  214. public abstract ByteBuffer Duplicate();
  215. public abstract byte Get();
  216. public abstract ByteBuffer Put(byte b);
  217. public abstract byte Get(int index);
  218. public abstract ByteBuffer Put(int index, byte b);
  219. public virtual ByteBuffer Get(byte[] dst, int offset, int length)
  220. {
  221. CheckBounds(offset, length, dst.Length);
  222. if (length > Remaining())
  223. throw new Exception("BufferUnderflowException");
  224. int end = offset + length;
  225. for (int i = offset; i < end; i++)
  226. dst[i] = Get();
  227. return this;
  228. }
  229. public virtual ByteBuffer Get(byte[] dst)
  230. {
  231. return Get(dst, 0, dst.Length);
  232. }
  233. public virtual ByteBuffer Put(ByteBuffer src)
  234. {
  235. if (src == this)
  236. throw new Exception("IllegalArgumentException");
  237. int n = src.Remaining();
  238. if (n > Remaining())
  239. throw new Exception("BufferOverflowException");
  240. for (int i = 0; i < n; i++)
  241. Put(src.Get());
  242. return this;
  243. }
  244. public virtual ByteBuffer Put(byte[] src, int offset, int length)
  245. {
  246. CheckBounds(offset, length, src.Length);
  247. if (length > Remaining())
  248. throw new Exception("BufferOverflowException");
  249. int end = offset + length;
  250. for (int i = offset; i < end; i++)
  251. this.Put(src[i]);
  252. return this;
  253. }
  254. public virtual ByteBuffer Put(byte[] src)
  255. {
  256. return Put(src, 0, src.Length);
  257. }
  258. public override bool HasArray()
  259. {
  260. return (hb != null);
  261. }
  262. public override Array Array()
  263. {
  264. if (hb == null)
  265. throw new Exception("UnsupportedOperationException");
  266. return hb;
  267. }
  268. public override int ArrayOffset()
  269. {
  270. if (hb == null)
  271. throw new Exception("UnsupportedOperationException");
  272. return offset;
  273. }
  274. public abstract ByteBuffer Compact();
  275. public override String ToString()
  276. {
  277. StringBuilder sb = new StringBuilder();
  278. sb.Append(GetType().Name);
  279. sb.Append("[pos=");
  280. sb.Append(Position());
  281. sb.Append(" lim=");
  282. sb.Append(Limit());
  283. sb.Append(" cap=");
  284. sb.Append(Capacity());
  285. sb.Append("]");
  286. return sb.ToString();
  287. }
  288. public override int GetHashCode()
  289. {
  290. int h = 1;
  291. int p = Position();
  292. for (int i = Limit() - 1; i >= p; i--)
  293. h = 31 * h + (int)Get(i);
  294. return h;
  295. }
  296. public override bool Equals(Object ob)
  297. {
  298. if (this == ob)
  299. return true;
  300. if (!(ob is ByteBuffer))
  301. return false;
  302. ByteBuffer that = (ByteBuffer)ob;
  303. if (this.Remaining() != that.Remaining())
  304. return false;
  305. int p = this.Position();
  306. for (int i = this.Limit() - 1, j = that.Limit() - 1; i >= p; i--, j--)
  307. if ((this.Get(i) != that.Get(j)))
  308. return false;
  309. return true;
  310. }
  311. }
  312. public class HeapByteBuffer : ByteBuffer
  313. {
  314. internal HeapByteBuffer(int cap, int lim)
  315. : base(-1, 0, lim, cap, new byte[cap], 0)
  316. { }
  317. internal HeapByteBuffer(byte[] buf, int off, int len)
  318. : base(-1, off, off + len, buf.Length, buf, 0)
  319. { }
  320. protected HeapByteBuffer(byte[] buf, int mark, int pos, int lim, int cap, int off)
  321. : base(mark, pos, lim, cap, buf, off)
  322. { }
  323. public override ByteBuffer Slice()
  324. {
  325. return new HeapByteBuffer(hb,
  326. -1,
  327. 0,
  328. this.Remaining(),
  329. this.Remaining(),
  330. this.Position() + offset);
  331. }
  332. public override ByteBuffer Duplicate()
  333. {
  334. return new HeapByteBuffer(hb,
  335. this.MarkValue(),
  336. this.Position(),
  337. this.Limit(),
  338. this.Capacity(),
  339. offset);
  340. }
  341. protected int ix(int i)
  342. {
  343. return i + offset;
  344. }
  345. public override byte Get()
  346. {
  347. return hb[ix(NextGetIndex())];
  348. }
  349. public override byte Get(int i)
  350. {
  351. return hb[ix(CheckIndex(i))];
  352. }
  353. public override ByteBuffer Get(byte[] dst, int offset, int length)
  354. {
  355. CheckBounds(offset, length, dst.Length);
  356. if (length > Remaining())
  357. throw new Exception("BufferUnderflowException");
  358. System.Buffer.BlockCopy(hb, ix(Position()), dst, offset, length);
  359. Position(Position() + length);
  360. return this;
  361. }
  362. public override bool IsReadOnly()
  363. {
  364. return false;
  365. }
  366. public override ByteBuffer Put(byte x)
  367. {
  368. hb[ix(NextPutIndex())] = x;
  369. return this;
  370. }
  371. public override ByteBuffer Put(int i, byte x)
  372. {
  373. hb[ix(CheckIndex(i))] = x;
  374. return this;
  375. }
  376. public override ByteBuffer Put(byte[] src, int offset, int length)
  377. {
  378. CheckBounds(offset, length, src.Length);
  379. if (length > Remaining())
  380. throw new Exception("BufferOverflowException");
  381. System.Buffer.BlockCopy(src, offset, hb, ix(Position()), length);
  382. Position(Position() + length);
  383. return this;
  384. }
  385. public override ByteBuffer Put(ByteBuffer src)
  386. {
  387. if (src is HeapByteBuffer)
  388. {
  389. if (src == this)
  390. throw new Exception("IllegalArgumentException");
  391. HeapByteBuffer sb = (HeapByteBuffer)src;
  392. int n = sb.Remaining();
  393. if (n > Remaining())
  394. throw new Exception("BufferOverflowException");
  395. System.Buffer.BlockCopy(sb.hb, sb.ix(sb.Position()),
  396. hb, ix(Position()), n);
  397. sb.Position(sb.Position() + n);
  398. Position(Position() + n);
  399. }
  400. else
  401. {
  402. base.Put(src);
  403. }
  404. return this;
  405. }
  406. public override ByteBuffer Compact()
  407. {
  408. System.Buffer.BlockCopy(hb, ix(Position()), hb, ix(0), Remaining());
  409. Position(Remaining());
  410. Limit(Capacity());
  411. DiscardMark();
  412. return this;
  413. }
  414. }
  415. }