View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  
19  package org.apache.hadoop.hbase.util;
20  
21  import org.apache.hadoop.hbase.classification.InterfaceAudience;
22  import org.apache.hadoop.hbase.classification.InterfaceStability;
23  
24  /**
25   * Extends the basic {@link AbstractPositionedByteRange} implementation with
26   * position support and it is a mutable version. {@code position} is considered transient,
27   * not fundamental to the definition of the range, and does not participate in
28   * {@link #compareTo(ByteRange)}, {@link #hashCode()}, or
29   * {@link #equals(Object)}. {@code Position} is retained by copy operations.
30   */
31  @InterfaceAudience.Public
32  @InterfaceStability.Evolving
33  @edu.umd.cs.findbugs.annotations.SuppressWarnings("EQ_DOESNT_OVERRIDE_EQUALS")
34  public class SimplePositionedMutableByteRange extends AbstractPositionedByteRange {
35    /**
36     * Create a new {@code PositionedByteRange} lacking a backing array and with
37     * an undefined viewport.
38     */
39    public SimplePositionedMutableByteRange() {
40      super();
41    }
42  
43    /**
44     * Create a new {@code PositionedByteRange} over a new backing array of size
45     * {@code capacity}. The range's offset and length are 0 and {@code capacity},
46     * respectively.
47     * 
48     * @param capacity
49     *          the size of the backing array.
50     */
51    public SimplePositionedMutableByteRange(int capacity) {
52      this(new byte[capacity]);
53    }
54  
55    /**
56     * Create a new {@code PositionedByteRange} over the provided {@code bytes}.
57     * 
58     * @param bytes
59     *          The array to wrap.
60     */
61    public SimplePositionedMutableByteRange(byte[] bytes) {
62      set(bytes);
63    }
64  
65    /**
66     * Create a new {@code PositionedByteRange} over the provided {@code bytes}.
67     * 
68     * @param bytes
69     *          The array to wrap.
70     * @param offset
71     *          The offset into {@code bytes} considered the beginning of this
72     *          range.
73     * @param length
74     *          The length of this range.
75     */
76    public SimplePositionedMutableByteRange(byte[] bytes, int offset, int length) {
77      set(bytes, offset, length);
78    }
79  
80    @Override
81    public PositionedByteRange unset() {
82      this.position = 0;
83      clearHashCache();
84      bytes = null;
85      offset = 0;
86      length = 0;
87      return this;
88    }
89  
90    @Override
91    public PositionedByteRange set(int capacity) {
92      this.position = 0;
93      super.set(capacity);
94      this.limit = capacity;
95      return this;
96    }
97  
98    @Override
99    public PositionedByteRange set(byte[] bytes) {
100     this.position = 0;
101     super.set(bytes);
102     this.limit = bytes.length;
103     return this;
104   }
105 
106   @Override
107   public PositionedByteRange set(byte[] bytes, int offset, int length) {
108     this.position = 0;
109     super.set(bytes, offset, length);
110     limit = length;
111     return this;
112   }
113 
114   /**
115    * Update the beginning of this range. {@code offset + length} may not be
116    * greater than {@code bytes.length}. Resets {@code position} to 0.
117    * 
118    * @param offset
119    *          the new start of this range.
120    * @return this.
121    */
122   @Override
123   public PositionedByteRange setOffset(int offset) {
124     this.position = 0;
125     super.setOffset(offset);
126     return this;
127   }
128 
129   /**
130    * Update the length of this range. {@code offset + length} should not be
131    * greater than {@code bytes.length}. If {@code position} is greater than the
132    * new {@code length}, sets {@code position} to {@code length}.
133    * 
134    * @param length
135    *          The new length of this range.
136    * @return this.
137    */
138   @Override
139   public PositionedByteRange setLength(int length) {
140     this.position = Math.min(position, length);
141     super.setLength(length);
142     return this;
143   }
144 
145   @Override
146   public PositionedByteRange put(byte val) {
147     put(position++, val);
148     return this;
149   }
150 
151   @Override
152   public PositionedByteRange put(byte[] val) {
153     if (0 == val.length)
154       return this;
155     return this.put(val, 0, val.length);
156   }
157 
158   @Override
159   public PositionedByteRange put(byte[] val, int offset, int length) {
160     if (0 == length)
161       return this;
162     put(position, val, offset, length);
163     this.position += length;
164     return this;
165   }
166 
167   @Override
168   public PositionedByteRange get(int index, byte[] dst) {
169     super.get(index, dst);
170     return this;
171   }
172 
173   @Override
174   public PositionedByteRange get(int index, byte[] dst, int offset, int length) {
175     super.get(index, dst, offset, length);
176     return this;
177   }
178 
179   @Override
180   public PositionedByteRange put(int index, byte val) {
181     bytes[offset + index] = val;
182     return this;
183   }
184 
185   @Override
186   public PositionedByteRange put(int index, byte[] val) {
187     if (0 == val.length)
188       return this;
189     return put(index, val, 0, val.length);
190   }
191 
192   @Override
193   public PositionedByteRange put(int index, byte[] val, int offset, int length) {
194     if (0 == length)
195       return this;
196     System.arraycopy(val, offset, this.bytes, this.offset + index, length);
197     return this;
198   }
199 
200   @Override
201   public PositionedByteRange deepCopy() {
202     SimplePositionedMutableByteRange clone = new SimplePositionedMutableByteRange(
203         deepCopyToNewArray());
204     clone.position = this.position;
205     return clone;
206   }
207 
208   @Override
209   public PositionedByteRange shallowCopy() {
210     SimplePositionedMutableByteRange clone = new SimplePositionedMutableByteRange(bytes, offset,
211         length);
212     clone.position = this.position;
213     return clone;
214   }
215 
216   @Override
217   public PositionedByteRange shallowCopySubRange(int innerOffset, int copyLength) {
218     SimplePositionedMutableByteRange clone = new SimplePositionedMutableByteRange(bytes, offset
219         + innerOffset, copyLength);
220     clone.position = this.position;
221     return clone;
222   }
223 
224   @Override
225   public PositionedByteRange putShort(short val) {
226     putShort(position, val);
227     position += Bytes.SIZEOF_SHORT;
228     return this;
229   }
230 
231   @Override
232   public PositionedByteRange putInt(int val) {
233     putInt(position, val);
234     position += Bytes.SIZEOF_INT;
235     return this;
236   }
237 
238   @Override
239   public PositionedByteRange putLong(long val) {
240     putLong(position, val);
241     position += Bytes.SIZEOF_LONG;
242     return this;
243   }
244 
245   @Override
246   public int putVLong(long val) {
247     int len = putVLong(position, val);
248     position += len;
249     return len;
250   }
251 
252   @Override
253   public PositionedByteRange putShort(int index, short val) {
254     // This writing is same as BB's putShort. When byte[] is wrapped in a BB and
255     // call putShort(),
256     // one can get the same result.
257     bytes[offset + index + 1] = (byte) val;
258     val >>= 8;
259     bytes[offset + index] = (byte) val;
260     clearHashCache();
261     return this;
262   }
263 
264   @Override
265   public PositionedByteRange putInt(int index, int val) {
266     // This writing is same as BB's putInt. When byte[] is wrapped in a BB and
267     // call getInt(), one
268     // can get the same result.
269     for (int i = Bytes.SIZEOF_INT - 1; i > 0; i--) {
270       bytes[offset + index + i] = (byte) val;
271       val >>>= 8;
272     }
273     bytes[offset + index] = (byte) val;
274     clearHashCache();
275     return this;
276   }
277 
278   @Override
279   public PositionedByteRange putLong(int index, long val) {
280     // This writing is same as BB's putLong. When byte[] is wrapped in a BB and
281     // call putLong(), one
282     // can get the same result.
283     for (int i = Bytes.SIZEOF_LONG - 1; i > 0; i--) {
284       bytes[offset + index + i] = (byte) val;
285       val >>>= 8;
286     }
287     bytes[offset + index] = (byte) val;
288     clearHashCache();
289     return this;
290   }
291 
292   // Copied from com.google.protobuf.CodedOutputStream
293   @Override
294   public int putVLong(int index, long val) {
295     int rPos = 0;
296     while (true) {
297       if ((val & ~0x7F) == 0) {
298         bytes[offset + index + rPos] = (byte) val;
299         break;
300       } else {
301         bytes[offset + index + rPos] = (byte) ((val & 0x7F) | 0x80);
302         val >>>= 7;
303       }
304       rPos++;
305     }
306     clearHashCache();
307     return rPos + 1;
308   }
309 
310 }