1 package org.apache.lucene.util;
3 import java.io.IOException;
4 import java.io.OutputStream;
7 * Licensed to the Apache Software Foundation (ASF) under one or more
8 * contributor license agreements. See the NOTICE file distributed with
9 * this work for additional information regarding copyright ownership.
10 * The ASF licenses this file to You under the Apache License, Version 2.0
11 * (the "License"); you may not use this file except in compliance with
12 * the License. You may obtain a copy of the License at
14 * http://www.apache.org/licenses/LICENSE-2.0
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.
24 * This class is used as a wrapper to a byte array, extending
25 * {@link OutputStream}. Data is written in the given byte[] buffer, until its
26 * length is insufficient. Than the buffer size is doubled and the data is
29 * This class is Unsafe as it is using a buffer which potentially can be changed
30 * from the outside. Moreover, when {@link #toByteArray()} is called, the buffer
31 * itself is returned, and not a copy.
33 * @lucene.experimental
35 public class UnsafeByteArrayOutputStream extends OutputStream {
37 private byte[] buffer;
39 private int startIndex;
42 * Constructs a new output stream, with a default allocated buffer which can
43 * later be obtained via {@link #toByteArray()}.
45 public UnsafeByteArrayOutputStream() {
46 reInit(new byte[32], 0);
50 * Constructs a new output stream, with a given buffer. Writing will start
51 * at index 0 as a default.
54 * some space to which writing will be made
56 public UnsafeByteArrayOutputStream(byte[] buffer) {
61 * Constructs a new output stream, with a given buffer. Writing will start
65 * some space to which writing will be made.
67 * an index (inclusive) from white data will be written.
69 public UnsafeByteArrayOutputStream(byte[] buffer, int startPos) {
70 reInit(buffer, startPos);
73 private void grow(int newLength) {
74 // It actually should be: (Java 1.6)
75 // buffer = Arrays.copyOf(buffer, newLength);
76 byte[] newBuffer = new byte[newLength];
77 System.arraycopy(buffer, 0, newBuffer, 0, buffer.length);
82 * For reuse-ability, this stream object can be re-initialized with another
83 * given buffer and starting position.
85 * @param buffer some space to which writing will be made.
86 * @param startPos an index (inclusive) from white data will be written.
88 public void reInit(byte[] buffer, int startPos) {
89 if (buffer.length == 0) {
90 throw new IllegalArgumentException("initial buffer length must be greater than 0.");
93 startIndex = startPos;
98 * For reuse-ability, this stream object can be re-initialized with another
99 * given buffer, using 0 as default starting position.
101 * @param buffer some space to which writing will be made.
103 public void reInit(byte[] buffer) {
108 * writes a given byte(at the form of an int) to the buffer. If the buffer's
109 * empty space is insufficient, the buffer is doubled.
111 * @param value byte value to be written
114 public void write(int value) throws IOException {
115 if (index >= buffer.length) {
116 grow(buffer.length << 1);
118 buffer[index++] = (byte) value;
122 * writes a given byte[], with offset and length to the buffer. If the
123 * buffer's empty space is insufficient, the buffer is doubled until it
124 * could contain all the data.
127 * byte buffer, containing the source data to be written
129 * index from which data from the buffer b should be written
131 * number of bytes that should be written
134 public void write(byte[] b, int off, int len) throws IOException {
135 // If there's not enough space for the data
136 int targetLength = index + len;
137 if (targetLength >= buffer.length) {
138 // Calculating the new required length of the array, keeping the array
139 // size a power of 2 if it was initialized like that.
140 int newlen = buffer.length;
141 while ((newlen <<= 1) < targetLength) {}
145 // Now that we have enough spare space, we could copy the rest of the
147 System.arraycopy(b, off, buffer, index, len);
149 // Updating the index to next available index.
154 * Returns the byte array saved within the buffer AS IS.
156 * @return the actual inner buffer - not a copy of it.
158 public byte[] toByteArray() {
163 * Returns the number of relevant bytes. This objects makes sure the buffer
164 * is at least the size of it's data. But it can also be twice as big. The
165 * user would want to process the relevant bytes only. For that he would
168 * @return number of relevant bytes
170 public int length() {
175 * Returns the start position data was written to. This is useful in case you
176 * used {@link #reInit(byte[], int)} or
177 * {@link #UnsafeByteArrayOutputStream(byte[], int)} and passed a start
178 * position which is not 0.
180 public int getStartPos() {