001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018
019 package org.apache.hadoop.record;
020
021 import java.io.UnsupportedEncodingException;
022
023 import org.apache.hadoop.classification.InterfaceAudience;
024 import org.apache.hadoop.classification.InterfaceStability;
025
026 /**
027 * A byte sequence that is used as a Java native type for buffer.
028 * It is resizable and distinguishes between the count of the seqeunce and
029 * the current capacity.
030 *
031 * @deprecated Replaced by <a href="https://hadoop.apache.org/avro/">Avro</a>.
032 */
033 @Deprecated
034 @InterfaceAudience.Public
035 @InterfaceStability.Stable
036 public class Buffer implements Comparable, Cloneable {
037 /** Number of valid bytes in this.bytes. */
038 private int count;
039 /** Backing store for Buffer. */
040 private byte[] bytes = null;
041
042 /**
043 * Create a zero-count sequence.
044 */
045 public Buffer() {
046 this.count = 0;
047 }
048
049 /**
050 * Create a Buffer using the byte array as the initial value.
051 *
052 * @param bytes This array becomes the backing storage for the object.
053 */
054 public Buffer(byte[] bytes) {
055 this.bytes = bytes;
056 this.count = (bytes == null) ? 0 : bytes.length;
057 }
058
059 /**
060 * Create a Buffer using the byte range as the initial value.
061 *
062 * @param bytes Copy of this array becomes the backing storage for the object.
063 * @param offset offset into byte array
064 * @param length length of data
065 */
066 public Buffer(byte[] bytes, int offset, int length) {
067 copy(bytes, offset, length);
068 }
069
070
071 /**
072 * Use the specified bytes array as underlying sequence.
073 *
074 * @param bytes byte sequence
075 */
076 public void set(byte[] bytes) {
077 this.count = (bytes == null) ? 0 : bytes.length;
078 this.bytes = bytes;
079 }
080
081 /**
082 * Copy the specified byte array to the Buffer. Replaces the current buffer.
083 *
084 * @param bytes byte array to be assigned
085 * @param offset offset into byte array
086 * @param length length of data
087 */
088 public final void copy(byte[] bytes, int offset, int length) {
089 if (this.bytes == null || this.bytes.length < length) {
090 this.bytes = new byte[length];
091 }
092 System.arraycopy(bytes, offset, this.bytes, 0, length);
093 this.count = length;
094 }
095
096 /**
097 * Get the data from the Buffer.
098 *
099 * @return The data is only valid between 0 and getCount() - 1.
100 */
101 public byte[] get() {
102 if (bytes == null) {
103 bytes = new byte[0];
104 }
105 return bytes;
106 }
107
108 /**
109 * Get the current count of the buffer.
110 */
111 public int getCount() {
112 return count;
113 }
114
115 /**
116 * Get the capacity, which is the maximum count that could handled without
117 * resizing the backing storage.
118 *
119 * @return The number of bytes
120 */
121 public int getCapacity() {
122 return this.get().length;
123 }
124
125 /**
126 * Change the capacity of the backing storage.
127 * The data is preserved if newCapacity >= getCount().
128 * @param newCapacity The new capacity in bytes.
129 */
130 public void setCapacity(int newCapacity) {
131 if (newCapacity < 0) {
132 throw new IllegalArgumentException("Invalid capacity argument "+newCapacity);
133 }
134 if (newCapacity == 0) {
135 this.bytes = null;
136 this.count = 0;
137 return;
138 }
139 if (newCapacity != getCapacity()) {
140 byte[] data = new byte[newCapacity];
141 if (newCapacity < count) {
142 count = newCapacity;
143 }
144 if (count != 0) {
145 System.arraycopy(this.get(), 0, data, 0, count);
146 }
147 bytes = data;
148 }
149 }
150
151 /**
152 * Reset the buffer to 0 size
153 */
154 public void reset() {
155 setCapacity(0);
156 }
157
158 /**
159 * Change the capacity of the backing store to be the same as the current
160 * count of buffer.
161 */
162 public void truncate() {
163 setCapacity(count);
164 }
165
166 /**
167 * Append specified bytes to the buffer.
168 *
169 * @param bytes byte array to be appended
170 * @param offset offset into byte array
171 * @param length length of data
172
173 */
174 public void append(byte[] bytes, int offset, int length) {
175 setCapacity(count+length);
176 System.arraycopy(bytes, offset, this.get(), count, length);
177 count = count + length;
178 }
179
180 /**
181 * Append specified bytes to the buffer
182 *
183 * @param bytes byte array to be appended
184 */
185 public void append(byte[] bytes) {
186 append(bytes, 0, bytes.length);
187 }
188
189 // inherit javadoc
190 @Override
191 public int hashCode() {
192 int hash = 1;
193 byte[] b = this.get();
194 for (int i = 0; i < count; i++)
195 hash = (31 * hash) + b[i];
196 return hash;
197 }
198
199 /**
200 * Define the sort order of the Buffer.
201 *
202 * @param other The other buffer
203 * @return Positive if this is bigger than other, 0 if they are equal, and
204 * negative if this is smaller than other.
205 */
206 @Override
207 public int compareTo(Object other) {
208 Buffer right = ((Buffer) other);
209 byte[] lb = this.get();
210 byte[] rb = right.get();
211 for (int i = 0; i < count && i < right.count; i++) {
212 int a = (lb[i] & 0xff);
213 int b = (rb[i] & 0xff);
214 if (a != b) {
215 return a - b;
216 }
217 }
218 return count - right.count;
219 }
220
221 // inherit javadoc
222 @Override
223 public boolean equals(Object other) {
224 if (other instanceof Buffer && this != other) {
225 return compareTo(other) == 0;
226 }
227 return (this == other);
228 }
229
230 // inheric javadoc
231 @Override
232 public String toString() {
233 StringBuilder sb = new StringBuilder(2*count);
234 for(int idx = 0; idx < count; idx++) {
235 sb.append(Character.forDigit((bytes[idx] & 0xF0) >> 4, 16));
236 sb.append(Character.forDigit(bytes[idx] & 0x0F, 16));
237 }
238 return sb.toString();
239 }
240
241 /**
242 * Convert the byte buffer to a string an specific character encoding
243 *
244 * @param charsetName Valid Java Character Set Name
245 */
246 public String toString(String charsetName)
247 throws UnsupportedEncodingException {
248 return new String(this.get(), 0, this.getCount(), charsetName);
249 }
250
251 // inherit javadoc
252 @Override
253 public Object clone() throws CloneNotSupportedException {
254 Buffer result = (Buffer) super.clone();
255 result.copy(this.get(), 0, this.getCount());
256 return result;
257 }
258 }