add --shared
[pylucene.git] / lucene-java-3.4.0 / lucene / contrib / facet / src / java / org / apache / lucene / util / UnsafeByteArrayOutputStream.java
1 package org.apache.lucene.util;
2
3 import java.io.IOException;
4 import java.io.OutputStream;
5
6 /**
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
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  */
22
23 /**
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
27  * written.
28  * 
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.
32  * 
33  * @lucene.experimental
34  */
35 public class UnsafeByteArrayOutputStream extends OutputStream {
36
37   private byte[] buffer;
38   private int index;
39   private int startIndex;
40
41   /**
42    * Constructs a new output stream, with a default allocated buffer which can
43    * later be obtained via {@link #toByteArray()}.
44    */
45   public UnsafeByteArrayOutputStream() {
46     reInit(new byte[32], 0);
47   }
48
49   /**
50    * Constructs a new output stream, with a given buffer. Writing will start
51    * at index 0 as a default.
52    * 
53    * @param buffer
54    *            some space to which writing will be made
55    */
56   public UnsafeByteArrayOutputStream(byte[] buffer) {
57     reInit(buffer, 0);
58   }
59
60   /**
61    * Constructs a new output stream, with a given buffer. Writing will start
62    * at a given index.
63    * 
64    * @param buffer
65    *            some space to which writing will be made.
66    * @param startPos
67    *            an index (inclusive) from white data will be written.
68    */
69   public UnsafeByteArrayOutputStream(byte[] buffer, int startPos) {
70     reInit(buffer, startPos);
71   }
72
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);
78     buffer = newBuffer;
79   }
80
81   /**
82    * For reuse-ability, this stream object can be re-initialized with another
83    * given buffer and starting position.
84    * 
85    * @param buffer some space to which writing will be made.
86    * @param startPos an index (inclusive) from white data will be written.
87    */
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.");
91     }
92     this.buffer = buffer;
93     startIndex = startPos;
94     index = startIndex;
95   }
96
97   /**
98    * For reuse-ability, this stream object can be re-initialized with another
99    * given buffer, using 0 as default starting position.
100    * 
101    * @param buffer some space to which writing will be made.
102    */
103   public void reInit(byte[] buffer) {
104     reInit(buffer, 0);
105   }
106
107   /**
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.
110    * 
111    * @param value byte value to be written
112    */
113   @Override
114   public void write(int value) throws IOException {
115     if (index >= buffer.length) {
116       grow(buffer.length << 1);
117     }
118     buffer[index++] = (byte) value;
119   }
120
121   /**
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.
125    * 
126    * @param b
127    *            byte buffer, containing the source data to be written
128    * @param off
129    *            index from which data from the buffer b should be written
130    * @param len
131    *            number of bytes that should be written
132    */
133   @Override
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) {}
142       grow(newlen);
143     }
144
145     // Now that we have enough spare space, we could copy the rest of the
146     // data
147     System.arraycopy(b, off, buffer, index, len);
148
149     // Updating the index to next available index.
150     index += len;
151   }
152
153   /**
154    * Returns the byte array saved within the buffer AS IS.
155    * 
156    * @return the actual inner buffer - not a copy of it.
157    */
158   public byte[] toByteArray() {
159     return buffer;
160   }
161
162   /**
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
166    * need the count.
167    * 
168    * @return number of relevant bytes
169    */
170   public int length() {
171     return index;
172   }
173
174   /**
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.
179    */
180   public int getStartPos() {
181     return startIndex;
182   }
183
184 }