PageRenderTime 80ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/components/forks/poi/src/loci/poi/poifs/storage/SmallDocumentBlock.java

http://github.com/openmicroscopy/bioformats
Java | 309 lines | 149 code | 42 blank | 118 comment | 12 complexity | e8d45aaab75f236cf3625cba098392df MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, Apache-2.0, BSD-2-Clause, MPL-2.0-no-copyleft-exception
  1. /*
  2. * #%L
  3. * Fork of Apache Jakarta POI.
  4. * %%
  5. * Copyright (C) 2008 - 2013 Open Microscopy Environment:
  6. * - Board of Regents of the University of Wisconsin-Madison
  7. * - Glencoe Software, Inc.
  8. * - University of Dundee
  9. * %%
  10. * Licensed under the Apache License, Version 2.0 (the "License");
  11. * you may not use this file except in compliance with the License.
  12. * You may obtain a copy of the License at
  13. *
  14. * http://www.apache.org/licenses/LICENSE-2.0
  15. *
  16. * Unless required by applicable law or agreed to in writing, software
  17. * distributed under the License is distributed on an "AS IS" BASIS,
  18. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  19. * See the License for the specific language governing permissions and
  20. * limitations under the License.
  21. * #L%
  22. */
  23. /* ====================================================================
  24. Licensed to the Apache Software Foundation (ASF) under one or more
  25. contributor license agreements. See the NOTICE file distributed with
  26. this work for additional information regarding copyright ownership.
  27. The ASF licenses this file to You under the Apache License, Version 2.0
  28. (the "License"); you may not use this file except in compliance with
  29. the License. You may obtain a copy of the License at
  30. http://www.apache.org/licenses/LICENSE-2.0
  31. Unless required by applicable law or agreed to in writing, software
  32. distributed under the License is distributed on an "AS IS" BASIS,
  33. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  34. See the License for the specific language governing permissions and
  35. limitations under the License.
  36. ==================================================================== */
  37. package loci.poi.poifs.storage;
  38. import java.io.*;
  39. import java.util.*;
  40. /**
  41. * Storage for documents that are too small to use regular
  42. * DocumentBlocks for their data
  43. *
  44. * @author Marc Johnson (mjohnson at apache dot org)
  45. */
  46. public class SmallDocumentBlock
  47. implements BlockWritable, ListManagedBlock
  48. {
  49. private byte[] _data;
  50. private static final byte _default_fill = ( byte ) 0xff;
  51. private static final int _block_size = 64;
  52. private int _blocks_per_big_block;
  53. private SmallDocumentBlock(final byte [] data, final int index, int size)
  54. {
  55. this(size);
  56. System.arraycopy(data, index * _block_size, _data, 0, _block_size);
  57. }
  58. private SmallDocumentBlock(int size)
  59. {
  60. _blocks_per_big_block = size / _block_size;
  61. _data = new byte[ _block_size ];
  62. }
  63. public int getBigBlockSize() { return _blocks_per_big_block * _block_size; }
  64. /**
  65. * convert a single long array into an array of SmallDocumentBlock
  66. * instances
  67. *
  68. * @param array the byte array to be converted
  69. * @param size the intended size of the array (which may be smaller)
  70. *
  71. * @return an array of SmallDocumentBlock instances, filled from
  72. * the array
  73. */
  74. public static SmallDocumentBlock [] convert(final byte [] array,
  75. final int size)
  76. {
  77. SmallDocumentBlock[] rval =
  78. new SmallDocumentBlock[ (size + _block_size - 1) / _block_size ];
  79. int offset = 0;
  80. for (int k = 0; k < rval.length; k++)
  81. {
  82. rval[ k ] = new SmallDocumentBlock(size);
  83. if (offset < array.length)
  84. {
  85. int length = Math.min(_block_size, array.length - offset);
  86. System.arraycopy(array, offset, rval[ k ]._data, 0, length);
  87. if (length != _block_size)
  88. {
  89. Arrays.fill(rval[ k ]._data, length, _block_size,
  90. _default_fill);
  91. }
  92. }
  93. else
  94. {
  95. Arrays.fill(rval[ k ]._data, _default_fill);
  96. }
  97. offset += _block_size;
  98. }
  99. return rval;
  100. }
  101. /**
  102. * fill out a List of SmallDocumentBlocks so that it fully occupies
  103. * a set of big blocks
  104. *
  105. * @param blocks the List to be filled out
  106. *
  107. * @return number of big blocks the list encompasses
  108. */
  109. public static int fill(final List blocks, int size)
  110. {
  111. int count = blocks.size();
  112. int big_block_count = (count + (size / _block_size) - 1)
  113. / (size / _block_size);
  114. int full_count = big_block_count * (size / _block_size);
  115. for (; count < full_count; count++)
  116. {
  117. blocks.add(makeEmptySmallDocumentBlock(
  118. (size / _block_size) * _block_size));
  119. }
  120. return big_block_count;
  121. }
  122. /**
  123. * Factory for creating SmallDocumentBlocks from DocumentBlocks
  124. *
  125. * @param store the original DocumentBlocks
  126. * @param size the total document size
  127. *
  128. * @return an array of new SmallDocumentBlocks instances
  129. *
  130. * @exception IOException on errors reading from the DocumentBlocks
  131. * @exception ArrayIndexOutOfBoundsException if, somehow, the store
  132. * contains less data than size indicates
  133. */
  134. public static SmallDocumentBlock [] convert(final BlockWritable [] store,
  135. final int size)
  136. throws IOException, ArrayIndexOutOfBoundsException
  137. {
  138. ByteArrayOutputStream stream = new ByteArrayOutputStream();
  139. for (int j = 0; j < store.length; j++)
  140. {
  141. store[ j ].writeBlocks(stream);
  142. }
  143. byte[] data = stream.toByteArray();
  144. SmallDocumentBlock[] rval =
  145. new SmallDocumentBlock[ convertToBlockCount(size) ];
  146. for (int index = 0; index < rval.length; index++)
  147. {
  148. rval[ index ] = new SmallDocumentBlock(data, index, size);
  149. }
  150. return rval;
  151. }
  152. /**
  153. * create a list of SmallDocumentBlock's from raw data
  154. *
  155. * @param blocks the raw data containing the SmallDocumentBlock
  156. * data
  157. *
  158. * @return a List of SmallDocumentBlock's extracted from the input
  159. *
  160. * @exception IOException
  161. */
  162. public static List extract(ListManagedBlock [] blocks, int size)
  163. throws IOException
  164. {
  165. List sdbs = new ArrayList();
  166. for (int j = 0; j < blocks.length; j++)
  167. {
  168. byte[] data = blocks[ j ].getData();
  169. for (int k = 0; k < (size / _block_size); k++)
  170. {
  171. sdbs.add(new SmallDocumentBlock(data, k, size));
  172. }
  173. }
  174. return sdbs;
  175. }
  176. /**
  177. * read data from an array of SmallDocumentBlocks
  178. *
  179. * @param blocks the blocks to read from
  180. * @param buffer the buffer to write the data into
  181. * @param offset the offset into the array of blocks to read from
  182. */
  183. public static void read(final BlockWritable [] blocks,
  184. final byte [] buffer, final int offset)
  185. {
  186. int firstBlockIndex = offset / _block_size;
  187. int firstBlockOffset = offset % _block_size;
  188. int lastBlockIndex = (offset + buffer.length - 1) / _block_size;
  189. if (firstBlockIndex == lastBlockIndex)
  190. {
  191. System.arraycopy(
  192. (( SmallDocumentBlock ) blocks[ firstBlockIndex ])._data,
  193. firstBlockOffset, buffer, 0, buffer.length);
  194. }
  195. else
  196. {
  197. int buffer_offset = 0;
  198. System.arraycopy(
  199. (( SmallDocumentBlock ) blocks[ firstBlockIndex ])._data,
  200. firstBlockOffset, buffer, buffer_offset,
  201. _block_size - firstBlockOffset);
  202. buffer_offset += _block_size - firstBlockOffset;
  203. for (int j = firstBlockIndex + 1; j < lastBlockIndex; j++)
  204. {
  205. System.arraycopy((( SmallDocumentBlock ) blocks[ j ])._data,
  206. 0, buffer, buffer_offset, _block_size);
  207. buffer_offset += _block_size;
  208. }
  209. System.arraycopy(
  210. (( SmallDocumentBlock ) blocks[ lastBlockIndex ])._data, 0,
  211. buffer, buffer_offset, buffer.length - buffer_offset);
  212. }
  213. }
  214. /**
  215. * Calculate the storage size of a set of SmallDocumentBlocks
  216. *
  217. * @param size number of SmallDocumentBlocks
  218. *
  219. * @return total size
  220. */
  221. public static int calcSize(int size)
  222. {
  223. return size * _block_size;
  224. }
  225. private static SmallDocumentBlock makeEmptySmallDocumentBlock(int size)
  226. {
  227. SmallDocumentBlock block = new SmallDocumentBlock(size);
  228. Arrays.fill(block._data, _default_fill);
  229. return block;
  230. }
  231. private static int convertToBlockCount(final int size)
  232. {
  233. return (size + _block_size - 1) / _block_size;
  234. }
  235. /* ********** START implementation of BlockWritable ********** */
  236. /**
  237. * Write the storage to an OutputStream
  238. *
  239. * @param stream the OutputStream to which the stored data should
  240. * be written
  241. *
  242. * @exception IOException on problems writing to the specified
  243. * stream
  244. */
  245. public void writeBlocks(final OutputStream stream)
  246. throws IOException
  247. {
  248. stream.write(_data);
  249. }
  250. /* ********** END implementation of BlockWritable ********** */
  251. /* ********** START implementation of ListManagedBlock ********** */
  252. /**
  253. * Get the data from the block
  254. *
  255. * @return the block's data as a byte array
  256. *
  257. * @exception IOException if there is no data
  258. */
  259. public byte [] getData()
  260. throws IOException
  261. {
  262. return _data;
  263. }
  264. /* ********** END implementation of ListManagedBlock ********** */
  265. } // end public class SmallDocumentBlock