PageRenderTime 345ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/android/src/com/hyk/io/buffer/ChannelDataBuffer.java

http://hyk-proxy.googlecode.com/
Java | 526 lines | 378 code | 63 blank | 85 comment | 31 complexity | 4490a5deec491ed9dc4aa6584511af57 MD5 | raw file
Possible License(s): LGPL-2.0, BSD-3-Clause, LGPL-2.1, GPL-3.0
  1. /**
  2. * This file is part of the hyk-util project.
  3. * Copyright (c) 2010 Yin QiWen <yinqiwen@gmail.com>
  4. *
  5. * Description: DataBuffer.java
  6. *
  7. * @author qiying.wang [ May 24, 2010 | 2:22:18 PM ]
  8. *
  9. */
  10. package com.hyk.io.buffer;
  11. import java.io.IOException;
  12. import java.nio.ByteBuffer;
  13. import java.util.ArrayList;
  14. import java.util.List;
  15. /**
  16. *
  17. */
  18. public class ChannelDataBuffer
  19. {
  20. // private static final int DEFAULT_BUFFER_SIZE = 256;
  21. private int readerIndex;
  22. private int writerIndex;
  23. private int markedReaderIndex;
  24. private int markedWriterIndex;
  25. private List<ByteArray> bufferList = new ArrayList<ByteArray>();
  26. public final OutputStream out = new OutputStream();
  27. public final InputStream in = new InputStream();
  28. private ChannelDataBuffer(byte[] buffer, int off, int len)
  29. {
  30. bufferList.add(new ByteArray(buffer, off, len));
  31. }
  32. public static ChannelDataBuffer wrap(byte[] buffer)
  33. {
  34. return new ChannelDataBuffer(buffer, 0, buffer.length);
  35. }
  36. public static ChannelDataBuffer wrap(byte[] buffer, int off, int len)
  37. {
  38. return new ChannelDataBuffer(buffer, off, len);
  39. }
  40. public static ChannelDataBuffer wrap(ChannelDataBuffer... buffers)
  41. {
  42. ChannelDataBuffer base = buffers[0];
  43. for(int i = 1; i < buffers.length; i++)
  44. {
  45. base.bufferList.addAll(buffers[i].bufferList);
  46. }
  47. return base;
  48. }
  49. public static ChannelDataBuffer allocate(int size)
  50. {
  51. return wrap(new byte[size]);
  52. }
  53. public java.io.OutputStream getOutputStream()
  54. {
  55. return out;
  56. }
  57. public java.io.InputStream getInputStream()
  58. {
  59. return in;
  60. }
  61. class OutputStream extends java.io.OutputStream
  62. {
  63. @Override
  64. public void write(int b) throws IOException
  65. {
  66. writeByte((byte)b);
  67. }
  68. @Override
  69. public void write(byte[] b, int off, int len) throws IOException
  70. {
  71. writeBytes(b, off, len);
  72. }
  73. @Override
  74. public void close() throws IOException
  75. {
  76. flip();
  77. }
  78. }
  79. class InputStream extends java.io.InputStream
  80. {
  81. @Override
  82. public int available() throws IOException
  83. {
  84. return readableBytes();
  85. }
  86. @Override
  87. public int read() throws IOException
  88. {
  89. if(!readable()) return -1;
  90. return readByte() & 0xff;
  91. }
  92. @Override
  93. public int read(byte[] b, int off, int len) throws IOException
  94. {
  95. if(!readable()) return -1;
  96. len = Math.min(len, readableBytes());
  97. readBytes(b, off, len);
  98. return len;
  99. }
  100. }
  101. public int readerIndex()
  102. {
  103. return readerIndex;
  104. }
  105. public void readerIndex(int readerIndex)
  106. {
  107. if(readerIndex < 0 || readerIndex > writerIndex)
  108. {
  109. throw new IndexOutOfBoundsException();
  110. }
  111. this.readerIndex = readerIndex;
  112. }
  113. public int writerIndex()
  114. {
  115. return writerIndex;
  116. }
  117. public void writerIndex(int writerIndex)
  118. {
  119. if(writerIndex < readerIndex || writerIndex > capacity())
  120. {
  121. throw new IndexOutOfBoundsException();
  122. }
  123. this.writerIndex = writerIndex;
  124. }
  125. public void setIndex(int readerIndex, int writerIndex)
  126. {
  127. if(readerIndex < 0 || readerIndex > writerIndex || writerIndex > capacity())
  128. {
  129. throw new IndexOutOfBoundsException();
  130. }
  131. this.readerIndex = readerIndex;
  132. this.writerIndex = writerIndex;
  133. }
  134. public void clear()
  135. {
  136. readerIndex = writerIndex = 0;
  137. }
  138. public boolean readable()
  139. {
  140. return readableBytes() > 0;
  141. }
  142. public boolean writable()
  143. {
  144. return writableBytes() > 0;
  145. }
  146. public int readableBytes()
  147. {
  148. return capacity() - readerIndex;
  149. }
  150. public int writableBytes()
  151. {
  152. return capacity() - writerIndex;
  153. }
  154. public void flip()
  155. {
  156. ByteArray buffer = getWriteBuffer(0);
  157. int offset = getWriteBufferOffset();
  158. buffer.length = offset - buffer.off;
  159. }
  160. public int capacity()
  161. {
  162. int capacity = 0;
  163. for(ByteArray buffer : bufferList)
  164. {
  165. capacity += buffer.capacity();
  166. }
  167. return capacity;
  168. }
  169. public void markReaderIndex()
  170. {
  171. markedReaderIndex = readerIndex;
  172. }
  173. public void resetReaderIndex()
  174. {
  175. readerIndex(markedReaderIndex);
  176. }
  177. public void markWriterIndex()
  178. {
  179. markedWriterIndex = writerIndex;
  180. }
  181. public void resetWriterIndex()
  182. {
  183. writerIndex = markedWriterIndex;
  184. }
  185. protected ByteArray allocateNewWriteBuffer(int expectedRemaining, int latestBufSize)
  186. {
  187. int allocateSize = Math.max(latestBufSize << 1, expectedRemaining);
  188. ByteArray buf = new ByteArray(allocateSize);
  189. bufferList.add(buf);
  190. return buf;
  191. }
  192. private ByteArray getWriteBuffer(int expectedRemaining)
  193. {
  194. int size = 0;
  195. int latestBufSize = 0;
  196. for(ByteArray buffer : bufferList)
  197. {
  198. latestBufSize = buffer.capacity();
  199. size += latestBufSize;
  200. if(size > (writerIndex))
  201. {
  202. return buffer;
  203. }
  204. }
  205. return allocateNewWriteBuffer(expectedRemaining, latestBufSize);
  206. }
  207. private ByteArray getReadBuffer()
  208. {
  209. int size = 0;
  210. int latestBufSize = 0;
  211. for(ByteArray buffer : bufferList)
  212. {
  213. latestBufSize = buffer.capacity();
  214. size += latestBufSize;
  215. if(size > readerIndex)
  216. {
  217. return buffer;
  218. }
  219. }
  220. throw new IndexOutOfBoundsException();
  221. }
  222. private int getWriteBufferOffset()
  223. {
  224. int size = 0;
  225. for(ByteArray buffer : bufferList)
  226. {
  227. size += buffer.capacity();
  228. if(size > (writerIndex))
  229. {
  230. int remain = (size - writerIndex);
  231. return buffer.capacity() - remain;
  232. }
  233. }
  234. return 0;
  235. }
  236. private int getReadBufferOffset()
  237. {
  238. int size = 0;
  239. for(ByteArray buffer : bufferList)
  240. {
  241. size += buffer.capacity();
  242. if(size > (readerIndex))
  243. {
  244. int remain = (size - readerIndex);
  245. return buffer.capacity() - remain;
  246. }
  247. }
  248. return 0;
  249. }
  250. public void writeBytes(byte[] src, int srcIndex, int length)
  251. {
  252. int writeTotalLen = 0;
  253. while(writeTotalLen < length)
  254. {
  255. ByteArray buffer = getWriteBuffer(length - writeTotalLen);
  256. int bufoff = getWriteBufferOffset();
  257. int remaining = buffer.capacity() - bufoff;
  258. int writeLen = remaining < (length - writeTotalLen) ? remaining : (length - writeTotalLen);
  259. System.arraycopy(src, srcIndex, buffer.array, bufoff + buffer.off, writeLen);
  260. // buffer.setBytes(src, srcIndex, writeLen);
  261. writeTotalLen += writeLen;
  262. srcIndex += writeLen;
  263. writerIndex += writeLen;
  264. }
  265. }
  266. public void writeBytes(ByteBuffer bytes)
  267. {
  268. int writeTotalLen = 0;
  269. int length = bytes.remaining();
  270. while(writeTotalLen < length)
  271. {
  272. ByteArray buffer = getWriteBuffer(length - writeTotalLen);
  273. int bufoff = getWriteBufferOffset();
  274. int remaining = buffer.capacity() - bufoff;
  275. int writeLen = remaining < (length - writeTotalLen) ? remaining : (length - writeTotalLen);
  276. bytes.get(buffer.array, buffer.off + bufoff, writeLen);
  277. // buffer.setBytes(src, srcIndex, writeLen);
  278. writeTotalLen += writeLen;
  279. writerIndex += writeLen;
  280. }
  281. }
  282. public void writeByte(byte value)
  283. {
  284. getWriteBuffer(1).set(getWriteBufferOffset(), value);
  285. writerIndex++;
  286. }
  287. public void writeBytes(byte[] src)
  288. {
  289. writeBytes(src, 0, src.length);
  290. }
  291. // public void writeBytes(DataBuffer src)
  292. // {
  293. // int writeTotalLen = 0;
  294. // int length = src.writableBytes();
  295. // while(writeTotalLen < length)
  296. // {
  297. // ByteArrayWrapper writeBuf = src.getReadBuffer();
  298. // int writeOff = src.getReadBufferOffset();
  299. // writeBytes(writeBuf.array, writeOff + writeBuf.off, writeBuf.length -
  300. // writeOff);
  301. // src.writerIndex += (writeBuf.length - writeOff);
  302. // writeTotalLen += (writeBuf.length - writeOff);
  303. // }
  304. // }
  305. // public void writeBytes(ByteBuffer src)
  306. // {
  307. // int length = src.remaining();
  308. // int writeTotalLen = 0;
  309. // while(writeTotalLen < length)
  310. // {
  311. // ByteArrayWrapper buffer = getWriteBuffer(length - writeTotalLen);
  312. // int bufoff = getWriteBufferOffset();
  313. // int remaining = buffer.capacity() - bufoff;
  314. // int writeLen = remaining < (length - writeTotalLen) ? remaining : (length
  315. // - writeTotalLen);
  316. // src.get(buffer.array, bufoff + buffer.off, writeLen);
  317. // //buffer.setByteBuffer(src, writeLen);
  318. // writeTotalLen += writeLen;
  319. // }
  320. // writerIndex += length;
  321. // }
  322. public byte readByte()
  323. {
  324. byte ret = getReadBuffer().get(getReadBufferOffset());
  325. readerIndex++;
  326. return ret;
  327. }
  328. public void readBytes(byte[] dst)
  329. {
  330. readBytes(dst, 0, dst.length);
  331. }
  332. public void readBytes(byte[] dst, int dstIndex, int length)
  333. {
  334. checkReadableBytes(length);
  335. int readTotalLen = 0;
  336. while(readTotalLen < length)
  337. {
  338. ByteArray buffer = getReadBuffer();
  339. int bufoff = getReadBufferOffset();
  340. int remaining = buffer.capacity() - bufoff;
  341. int writeLen = remaining < (length - readTotalLen) ? remaining : (length - readTotalLen);
  342. System.arraycopy(buffer.array, buffer.off + bufoff, dst, dstIndex, writeLen);
  343. readTotalLen += writeLen;
  344. dstIndex += writeLen;
  345. readerIndex += writeLen;
  346. }
  347. }
  348. public ByteBuffer readByteBuffer(int length)
  349. {
  350. checkReadableBytes(length);
  351. ByteArray buffer = getReadBuffer();
  352. int bufoff = getReadBufferOffset();
  353. int remaining = buffer.capacity() - bufoff;
  354. if(remaining >= length)
  355. {
  356. // avoid array copy
  357. return ByteBuffer.wrap(buffer.array, buffer.off + bufoff, length);
  358. }
  359. int readTotalLen = 0;
  360. ByteBuffer ret = ByteBuffer.allocate(length);
  361. while(readTotalLen < length)
  362. {
  363. int writeLen = remaining < (length - readTotalLen) ? remaining : (length - readTotalLen);
  364. // System.arraycopy(buffer, bufoff, dst, dstIndex, writeLen);
  365. ret.put(buffer.array, buffer.off + bufoff, writeLen);
  366. readTotalLen += writeLen;
  367. buffer = getReadBuffer();
  368. bufoff = getReadBufferOffset();
  369. remaining = buffer.capacity() - bufoff;
  370. readerIndex += writeLen;
  371. }
  372. ret.flip();
  373. return ret;
  374. }
  375. // public void readBytes(ByteBuffer dst)
  376. // {
  377. // int length = dst.remaining();
  378. // dst.mark();
  379. // checkReadableBytes(dst.remaining());
  380. // int readTotalLen = 0;
  381. // while(readTotalLen < length)
  382. // {
  383. // ByteArrayWrapper buffer = getReadBuffer();
  384. // int bufoff = getReadBufferOffset();
  385. // int remaining = buffer.capacity() - bufoff;
  386. // int writeLen = remaining < (length - readTotalLen) ? remaining : (length
  387. // - readTotalLen);
  388. // if(length == writeLen)
  389. // {
  390. //
  391. // }
  392. // //System.arraycopy(buffer, bufoff, dst, dstIndex, writeLen);
  393. // readTotalLen += writeLen;
  394. // //dstIndex += writeLen;
  395. // }
  396. // dst.reset();
  397. // }
  398. // public void readBytes(ByteArray dst)
  399. // {
  400. // int readTotalLen = 0;
  401. // int length = readableBytes();
  402. // while(readTotalLen < length)
  403. // {
  404. // Buffer writeBuf = getReadBuffer();
  405. // int writeOff = getReadBufferOffset();
  406. // dst.writeBytes(writeBuf.array, writeOff + writeBuf.off, writeBuf.length -
  407. // writeOff);
  408. // readerIndex += (writeBuf.length - writeOff);
  409. // readTotalLen += (writeBuf.length - writeOff);
  410. // }
  411. // }
  412. protected void checkReadableBytes(int minimumReadableBytes)
  413. {
  414. if(readableBytes() < minimumReadableBytes)
  415. {
  416. throw new IndexOutOfBoundsException();
  417. }
  418. }
  419. public static byte[] asByteArray(ChannelDataBuffer buffer)
  420. {
  421. if(buffer.bufferList.size() == 1)
  422. {
  423. ByteArray array = buffer.bufferList.get(0);
  424. if(array.length == array.array.length && array.off == 0)
  425. {
  426. return array.array;
  427. }
  428. }
  429. byte[] ret = new byte[buffer.capacity()];
  430. buffer.readBytes(ret);
  431. return ret;
  432. }
  433. public static ByteBuffer asByteBuffer(ChannelDataBuffer buffer)
  434. {
  435. if(buffer.bufferList.size() == 1)
  436. {
  437. ByteArray array = buffer.bufferList.get(0);
  438. return ByteBuffer.wrap(array.array, array.off, array.length);
  439. }
  440. ByteBuffer ret = ByteBuffer.allocate(buffer.capacity());
  441. for(ByteArray array : buffer.bufferList)
  442. {
  443. ret.put(array.array, array.off, array.length);
  444. }
  445. ret.flip();
  446. return ret;
  447. }
  448. public static ByteBuffer[] asByteBuffers(ChannelDataBuffer buffer)
  449. {
  450. ByteBuffer[] ret = new ByteBuffer[buffer.bufferList.size()];
  451. for(int i = 0; i < ret.length; i++)
  452. {
  453. ByteArray array = buffer.bufferList.get(i);
  454. ret[i] = ByteBuffer.wrap(array.array, array.off, array.length);
  455. }
  456. return ret;
  457. }
  458. @Override
  459. public String toString()
  460. {
  461. return getClass().getSimpleName() + '(' + "ridx=" + readerIndex + ", " + "widx=" + writerIndex + ", " + "cap=" + capacity() + ')';
  462. }
  463. }