1
2 package org.galagosearch.core.index;
3
4 import java.io.IOException;
5 import java.io.OutputStream;
6
7 /***
8 * Stores lists of integers in vbyte compressed form. This
9 * is useful for buffering data that will be stored
10 * compressed on disk.
11 */
12 public class CompressedByteBuffer {
13 byte[] values;
14 int position;
15
16 public CompressedByteBuffer() {
17 clear();
18 }
19
20 /***
21 * Add a single byte to the buffer. This byte is written
22 * directly to the buffer without compression.
23 *
24 * @param value The byte value to add.
25 */
26 public void addRaw(int value) {
27 if (position >= values.length) {
28 byte[] nValues = new byte[values.length * 2];
29 System.arraycopy(values, 0, nValues, 0, values.length);
30 values = nValues;
31 }
32
33 values[position] = (byte) value;
34 position += 1;
35 }
36
37 /***
38 * Adds a single number to the buffer. This number is
39 * converted to compressed form before it is stored.
40 */
41 public void add(long i) {
42 if (i < 1 << 7) {
43 addRaw((int) (i | 0x80));
44 } else if (i < 1 << 14) {
45 addRaw((int) (i >> 0) & 0x7f);
46 addRaw((int) ((i >> 7) & 0x7f) | 0x80);
47 } else if (i < 1 << 21) {
48 addRaw((int) (i >> 0) & 0x7f);
49 addRaw((int) (i >> 7) & 0x7f);
50 addRaw((int) ((i >> 14) & 0x7f) | 0x80);
51 } else {
52 while (i >= 1 << 7) {
53 addRaw((int) (i & 0x7f));
54 i >>= 7;
55 }
56
57 addRaw((int) (i | 0x80));
58 }
59 }
60
61 /***
62 * Adds a floating point value, (4 bytes) to the buffer.
63 * This is an uncompressed value.
64 */
65 public void addFloat(float value) {
66 int bits = Float.floatToIntBits(value);
67
68 addRaw((bits >>> 24) & 0xFF);
69 addRaw((bits >>> 16) & 0xFF);
70 addRaw((bits >>> 8) & 0xFF);
71 addRaw(bits & 0xFF);
72 }
73
74 /***
75 * Copies the entire contents of another compressed
76 * buffer to the end of this one.
77 *
78 * @param other The buffer to copy.
79 */
80 public void add(CompressedByteBuffer other) {
81 int totalLength = other.length() + length();
82 byte[] newValues = new byte[totalLength];
83
84 System.arraycopy(values, 0, newValues, 0, position);
85 System.arraycopy(other.values, 0, newValues, position, other.position);
86 values = newValues;
87 position = totalLength;
88 }
89
90 /***
91 * Erases the contents of this buffer and sets its
92 * length to zero.
93 */
94 public void clear() {
95 values = new byte[16];
96 position = 0;
97 }
98
99 /***
100 * Returns a byte array containing the contents of this buffer.
101 * The array returned may be larger than the actual length of
102 * the stored data. Use the length method to determine the
103 * true data length.
104 */
105 public byte[] getBytes() {
106 return values;
107 }
108
109 /***
110 * Returns the length of the data stored in this buffer.
111 */
112 public int length() {
113 return position;
114 }
115
116 /***
117 * Writes the contents of this buffer to a stream.
118 */
119 public void write(OutputStream stream) throws IOException {
120 stream.write(values, 0, position);
121 }
122 }
123