Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. /* ====================================================================
  2. Licensed to the Apache Software Foundation (ASF) under one or more
  3. contributor license agreements. See the NOTICE file distributed with
  4. this work for additional information regarding copyright ownership.
  5. The ASF licenses this file to You under the Apache License, Version 2.0
  6. (the "License"); you may not use this file except in compliance with
  7. the License. You may obtain a copy of the License at
  8. http://www.apache.org/licenses/LICENSE-2.0
  9. Unless required by applicable law or agreed to in writing, software
  10. distributed under the License is distributed on an "AS IS" BASIS,
  11. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. See the License for the specific language governing permissions and
  13. limitations under the License.
  14. ==================================================================== */
  15. package org.apache.poi.poifs.storage;
  16. /**
  17. * Wraps a <tt>byte</tt> array and provides simple data input access.
  18. * Internally, this class maintains a buffer read index, so that for the most part, primitive
  19. * data can be read in a data-input-stream-like manner.<p/>
  20. *
  21. * Note - the calling class should call the {@link #available()} method to detect end-of-buffer
  22. * and move to the next data block when the current is exhausted.
  23. * For optimisation reasons, no error handling is performed in this class. Thus, mistakes in
  24. * calling code ran may raise ugly exceptions here, like {@link ArrayIndexOutOfBoundsException},
  25. * etc .<p/>
  26. *
  27. * The multi-byte primitive input methods ({@link #readUShortLE()}, {@link #readIntLE()} and
  28. * {@link #readLongLE()}) have corresponding 'spanning read' methods which (when required) perform
  29. * a read across the block boundary. These spanning read methods take the previous
  30. * {@link DataInputBlock} as a parameter.
  31. * Reads of larger amounts of data (into <tt>byte</tt> array buffers) must be managed by the caller
  32. * since these could conceivably involve more than two blocks.
  33. *
  34. * @author Josh Micich
  35. */
  36. public final class DataInputBlock {
  37. /**
  38. * Possibly any size (usually 512K or 64K). Assumed to be at least 8 bytes for all blocks
  39. * before the end of the stream. The last block in the stream can be any size except zero.
  40. */
  41. private final byte[] _buf;
  42. private int _readIndex;
  43. private int _maxIndex;
  44. DataInputBlock(byte[] data, int startOffset) {
  45. _buf = data;
  46. _readIndex = startOffset;
  47. _maxIndex = _buf.length;
  48. }
  49. public int available() {
  50. return _maxIndex-_readIndex;
  51. }
  52. public int readUByte() {
  53. return _buf[_readIndex++] & 0xFF;
  54. }
  55. /**
  56. * Reads a <tt>short</tt> which was encoded in <em>little endian</em> format.
  57. */
  58. public int readUShortLE() {
  59. int i = _readIndex;
  60. int b0 = _buf[i++] & 0xFF;
  61. int b1 = _buf[i++] & 0xFF;
  62. _readIndex = i;
  63. return (b1 << 8) + (b0 << 0);
  64. }
  65. /**
  66. * Reads a <tt>short</tt> which spans the end of <tt>prevBlock</tt> and the start of this block.
  67. */
  68. public int readUShortLE(DataInputBlock prevBlock) {
  69. // simple case - will always be one byte in each block
  70. int i = prevBlock._buf.length-1;
  71. int b0 = prevBlock._buf[i++] & 0xFF;
  72. int b1 = _buf[_readIndex++] & 0xFF;
  73. return (b1 << 8) + (b0 << 0);
  74. }
  75. /**
  76. * Reads an <tt>int</tt> which was encoded in <em>little endian</em> format.
  77. */
  78. public int readIntLE() {
  79. int i = _readIndex;
  80. int b0 = _buf[i++] & 0xFF;
  81. int b1 = _buf[i++] & 0xFF;
  82. int b2 = _buf[i++] & 0xFF;
  83. int b3 = _buf[i++] & 0xFF;
  84. _readIndex = i;
  85. return (b3 << 24) + (b2 << 16) + (b1 << 8) + (b0 << 0);
  86. }
  87. /**
  88. * Reads an <tt>int</tt> which spans the end of <tt>prevBlock</tt> and the start of this block.
  89. */
  90. public int readIntLE(DataInputBlock prevBlock, int prevBlockAvailable) {
  91. byte[] buf = new byte[4];
  92. readSpanning(prevBlock, prevBlockAvailable, buf);
  93. int b0 = buf[0] & 0xFF;
  94. int b1 = buf[1] & 0xFF;
  95. int b2 = buf[2] & 0xFF;
  96. int b3 = buf[3] & 0xFF;
  97. return (b3 << 24) + (b2 << 16) + (b1 << 8) + (b0 << 0);
  98. }
  99. /**
  100. * Reads a <tt>long</tt> which was encoded in <em>little endian</em> format.
  101. */
  102. public long readLongLE() {
  103. int i = _readIndex;
  104. int b0 = _buf[i++] & 0xFF;
  105. int b1 = _buf[i++] & 0xFF;
  106. int b2 = _buf[i++] & 0xFF;
  107. int b3 = _buf[i++] & 0xFF;
  108. int b4 = _buf[i++] & 0xFF;
  109. int b5 = _buf[i++] & 0xFF;
  110. int b6 = _buf[i++] & 0xFF;
  111. int b7 = _buf[i++] & 0xFF;
  112. _readIndex = i;
  113. return (((long)b7 << 56) +
  114. ((long)b6 << 48) +
  115. ((long)b5 << 40) +
  116. ((long)b4 << 32) +
  117. ((long)b3 << 24) +
  118. (b2 << 16) +
  119. (b1 << 8) +
  120. (b0 << 0));
  121. }
  122. /**
  123. * Reads a <tt>long</tt> which spans the end of <tt>prevBlock</tt> and the start of this block.
  124. */
  125. public long readLongLE(DataInputBlock prevBlock, int prevBlockAvailable) {
  126. byte[] buf = new byte[8];
  127. readSpanning(prevBlock, prevBlockAvailable, buf);
  128. int b0 = buf[0] & 0xFF;
  129. int b1 = buf[1] & 0xFF;
  130. int b2 = buf[2] & 0xFF;
  131. int b3 = buf[3] & 0xFF;
  132. int b4 = buf[4] & 0xFF;
  133. int b5 = buf[5] & 0xFF;
  134. int b6 = buf[6] & 0xFF;
  135. int b7 = buf[7] & 0xFF;
  136. return (((long)b7 << 56) +
  137. ((long)b6 << 48) +
  138. ((long)b5 << 40) +
  139. ((long)b4 << 32) +
  140. ((long)b3 << 24) +
  141. (b2 << 16) +
  142. (b1 << 8) +
  143. (b0 << 0));
  144. }
  145. /**
  146. * Reads a small amount of data from across the boundary between two blocks.
  147. * The {@link #_readIndex} of this (the second) block is updated accordingly.
  148. * Note- this method (and other code) assumes that the second {@link DataInputBlock}
  149. * always is big enough to complete the read without being exhausted.
  150. */
  151. private void readSpanning(DataInputBlock prevBlock, int prevBlockAvailable, byte[] buf) {
  152. System.arraycopy(prevBlock._buf, prevBlock._readIndex, buf, 0, prevBlockAvailable);
  153. int secondReadLen = buf.length-prevBlockAvailable;
  154. System.arraycopy(_buf, 0, buf, prevBlockAvailable, secondReadLen);
  155. _readIndex = secondReadLen;
  156. }
  157. /**
  158. * Reads <tt>len</tt> bytes from this block into the supplied buffer.
  159. */
  160. public void readFully(byte[] buf, int off, int len) {
  161. System.arraycopy(_buf, _readIndex, buf, off, len);
  162. _readIndex += len;
  163. }
  164. }