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.classification.InterfaceAudience;
22  import org.apache.hadoop.classification.InterfaceStability;
23  
24  /**
25   * A basic mutable {@link ByteRange} implementation.
26   */
27  @InterfaceAudience.Public
28  @InterfaceStability.Evolving
29  public class SimpleMutableByteRange extends AbstractByteRange {
30  
31    /**
32     * Create a new {@code ByteRange} lacking a backing array and with an
33     * undefined viewport.
34     */
35    public SimpleMutableByteRange() {
36      unset();
37    }
38  
39    /**
40     * Create a new {@code ByteRange} over a new backing array of size
41     * {@code capacity}. The range's offset and length are 0 and {@code capacity},
42     * respectively.
43     * 
44     * @param capacity
45     *          the size of the backing array.
46     */
47    public SimpleMutableByteRange(int capacity) {
48      this(new byte[capacity]);
49    }
50  
51    /**
52     * Create a new {@code ByteRange} over the provided {@code bytes}.
53     * 
54     * @param bytes
55     *          The array to wrap.
56     */
57    public SimpleMutableByteRange(byte[] bytes) {
58      set(bytes);
59    }
60  
61    /**
62     * Create a new {@code ByteRange} over the provided {@code bytes}.
63     *
64     * @param bytes
65     *          The array to wrap.
66     * @param offset
67     *          The offset into {@code bytes} considered the beginning of this
68     *          range.
69     * @param length
70     *          The length of this range.
71     */
72    public SimpleMutableByteRange(byte[] bytes, int offset, int length) {
73      set(bytes, offset, length);
74    }
75  
76    @Override
77    public ByteRange unset() {
78      clearHashCache();
79      bytes = null;
80      offset = 0;
81      length = 0;
82      return this;
83    }
84  
85    @Override
86    public ByteRange put(int index, byte val) {
87      bytes[offset + index] = val;
88      clearHashCache();
89      return this;
90    }
91  
92    @Override
93    public ByteRange put(int index, byte[] val) {
94      if (0 == val.length)
95        return this;
96      return put(index, val, 0, val.length);
97    }
98  
99    @Override
100   public ByteRange put(int index, byte[] val, int offset, int length) {
101     if (0 == length)
102       return this;
103     System.arraycopy(val, offset, this.bytes, this.offset + index, length);
104     clearHashCache();
105     return this;
106   }
107 
108   @Override
109   public ByteRange putShort(int index, short val) {
110     // This writing is same as BB's putShort. When byte[] is wrapped in a BB and
111     // call putShort(),
112     // one can get the same result.
113     bytes[offset + index + 1] = (byte) val;
114     val >>= 8;
115     bytes[offset + index] = (byte) val;
116     clearHashCache();
117     return this;
118   }
119 
120   @Override
121   public ByteRange putInt(int index, int val) {
122     // This writing is same as BB's putInt. When byte[] is wrapped in a BB and
123     // call getInt(), one
124     // can get the same result.
125     for (int i = Bytes.SIZEOF_INT - 1; i > 0; i--) {
126       bytes[offset + index + i] = (byte) val;
127       val >>>= 8;
128     }
129     bytes[offset + index] = (byte) val;
130     clearHashCache();
131     return this;
132   }
133 
134   @Override
135   public ByteRange putLong(int index, long val) {
136     // This writing is same as BB's putLong. When byte[] is wrapped in a BB and
137     // call putLong(), one
138     // can get the same result.
139     for (int i = Bytes.SIZEOF_LONG - 1; i > 0; i--) {
140       bytes[offset + index + i] = (byte) val;
141       val >>>= 8;
142     }
143     bytes[offset + index] = (byte) val;
144     clearHashCache();
145     return this;
146   }
147 
148   // Copied from com.google.protobuf.CodedOutputStream
149   @Override
150   public int putVLong(int index, long val) {
151     int rPos = 0;
152     while (true) {
153       if ((val & ~0x7F) == 0) {
154         bytes[offset + index + rPos] = (byte) val;
155         break;
156       } else {
157         bytes[offset + index + rPos] = (byte) ((val & 0x7F) | 0x80);
158         val >>>= 7;
159       }
160       rPos++;
161     }
162     clearHashCache();
163     return rPos + 1;
164   }
165 
166   @Override
167   public ByteRange deepCopy() {
168     SimpleMutableByteRange clone = new SimpleMutableByteRange(deepCopyToNewArray());
169     if (isHashCached()) {
170       clone.hash = hash;
171     }
172     return clone;
173   }
174 
175   @Override
176   public ByteRange shallowCopy() {
177     SimpleMutableByteRange clone = new SimpleMutableByteRange(bytes, offset, length);
178     if (isHashCached()) {
179       clone.hash = hash;
180     }
181     return clone;
182   }
183 
184   @Override
185   public ByteRange shallowCopySubRange(int innerOffset, int copyLength) {
186     SimpleMutableByteRange clone = new SimpleMutableByteRange(bytes, offset + innerOffset,
187         copyLength);
188     if (isHashCached()) {
189       clone.hash = hash;
190     }
191     return clone;
192   }
193 
194   @Override
195   public boolean equals(Object thatObject) {
196     if (thatObject == null) {
197       return false;
198     }
199     if (this == thatObject) {
200       return true;
201     }
202     if (hashCode() != thatObject.hashCode()) {
203       return false;
204     }
205     if (!(thatObject instanceof SimpleMutableByteRange)) {
206       return false;
207     }
208     SimpleMutableByteRange that = (SimpleMutableByteRange) thatObject;
209     return Bytes.equals(bytes, offset, length, that.bytes, that.offset, that.length);
210   }
211 
212 }