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   * The portion of this file denoted by 'Copied from com.google.protobuf.CodedOutputStream'
19   * is from Protocol Buffers v2.5.0 under the following license
20   *
21   * Copyright 2008 Google Inc.  All rights reserved.
22   * http://code.google.com/p/protobuf/
23   *
24   * Redistribution and use in source and binary forms, with or without
25   * modification, are permitted provided that the following conditions are
26   * met:
27   *
28   *     * Redistributions of source code must retain the above copyright
29   * notice, this list of conditions and the following disclaimer.
30   *     * Redistributions in binary form must reproduce the above
31   * copyright notice, this list of conditions and the following disclaimer
32   * in the documentation and/or other materials provided with the
33   * distribution.
34   *     * Neither the name of Google Inc. nor the names of its
35   * contributors may be used to endorse or promote products derived from
36   * this software without specific prior written permission.
37   *
38   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
39   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
40   * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
41   * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
42   * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
43   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
44   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
45   * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
46   * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
47   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
48   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
49   */
50  
51  package org.apache.hadoop.hbase.util;
52  
53  import org.apache.hadoop.hbase.classification.InterfaceAudience;
54  import org.apache.hadoop.hbase.classification.InterfaceStability;
55  
56  /**
57   * A basic mutable {@link ByteRange} implementation.
58   */
59  @InterfaceAudience.Public
60  @InterfaceStability.Evolving
61  public class SimpleMutableByteRange extends AbstractByteRange {
62  
63    /**
64     * Create a new {@code ByteRange} lacking a backing array and with an
65     * undefined viewport.
66     */
67    public SimpleMutableByteRange() {
68      unset();
69    }
70  
71    /**
72     * Create a new {@code ByteRange} over a new backing array of size
73     * {@code capacity}. The range's offset and length are 0 and {@code capacity},
74     * respectively.
75     * 
76     * @param capacity
77     *          the size of the backing array.
78     */
79    public SimpleMutableByteRange(int capacity) {
80      this(new byte[capacity]);
81    }
82  
83    /**
84     * Create a new {@code ByteRange} over the provided {@code bytes}.
85     * 
86     * @param bytes
87     *          The array to wrap.
88     */
89    public SimpleMutableByteRange(byte[] bytes) {
90      set(bytes);
91    }
92  
93    /**
94     * Create a new {@code ByteRange} over the provided {@code bytes}.
95     *
96     * @param bytes
97     *          The array to wrap.
98     * @param offset
99     *          The offset into {@code bytes} considered the beginning of this
100    *          range.
101    * @param length
102    *          The length of this range.
103    */
104   public SimpleMutableByteRange(byte[] bytes, int offset, int length) {
105     set(bytes, offset, length);
106   }
107 
108   @Override
109   public ByteRange unset() {
110     clearHashCache();
111     bytes = null;
112     offset = 0;
113     length = 0;
114     return this;
115   }
116 
117   @Override
118   public ByteRange put(int index, byte val) {
119     bytes[offset + index] = val;
120     clearHashCache();
121     return this;
122   }
123 
124   @Override
125   public ByteRange put(int index, byte[] val) {
126     if (0 == val.length)
127       return this;
128     return put(index, val, 0, val.length);
129   }
130 
131   @Override
132   public ByteRange put(int index, byte[] val, int offset, int length) {
133     if (0 == length)
134       return this;
135     System.arraycopy(val, offset, this.bytes, this.offset + index, length);
136     clearHashCache();
137     return this;
138   }
139 
140   @Override
141   public ByteRange putShort(int index, short val) {
142     // This writing is same as BB's putShort. When byte[] is wrapped in a BB and
143     // call putShort(),
144     // one can get the same result.
145     bytes[offset + index + 1] = (byte) val;
146     val >>= 8;
147     bytes[offset + index] = (byte) val;
148     clearHashCache();
149     return this;
150   }
151 
152   @Override
153   public ByteRange putInt(int index, int val) {
154     // This writing is same as BB's putInt. When byte[] is wrapped in a BB and
155     // call getInt(), one
156     // can get the same result.
157     for (int i = Bytes.SIZEOF_INT - 1; i > 0; i--) {
158       bytes[offset + index + i] = (byte) val;
159       val >>>= 8;
160     }
161     bytes[offset + index] = (byte) val;
162     clearHashCache();
163     return this;
164   }
165 
166   @Override
167   public ByteRange putLong(int index, long val) {
168     // This writing is same as BB's putLong. When byte[] is wrapped in a BB and
169     // call putLong(), one
170     // can get the same result.
171     for (int i = Bytes.SIZEOF_LONG - 1; i > 0; i--) {
172       bytes[offset + index + i] = (byte) val;
173       val >>>= 8;
174     }
175     bytes[offset + index] = (byte) val;
176     clearHashCache();
177     return this;
178   }
179 
180   // Copied from com.google.protobuf.CodedOutputStream v2.5.0 writeRawVarint64
181   @Override
182   public int putVLong(int index, long val) {
183     int rPos = 0;
184     while (true) {
185       if ((val & ~0x7F) == 0) {
186         bytes[offset + index + rPos] = (byte) val;
187         break;
188       } else {
189         bytes[offset + index + rPos] = (byte) ((val & 0x7F) | 0x80);
190         val >>>= 7;
191       }
192       rPos++;
193     }
194     clearHashCache();
195     return rPos + 1;
196   }
197   // end copied from protobuf
198 
199   @Override
200   public ByteRange deepCopy() {
201     SimpleMutableByteRange clone = new SimpleMutableByteRange(deepCopyToNewArray());
202     if (isHashCached()) {
203       clone.hash = hash;
204     }
205     return clone;
206   }
207 
208   @Override
209   public ByteRange shallowCopy() {
210     SimpleMutableByteRange clone = new SimpleMutableByteRange(bytes, offset, length);
211     if (isHashCached()) {
212       clone.hash = hash;
213     }
214     return clone;
215   }
216 
217   @Override
218   public ByteRange shallowCopySubRange(int innerOffset, int copyLength) {
219     SimpleMutableByteRange clone = new SimpleMutableByteRange(bytes, offset + innerOffset,
220         copyLength);
221     if (isHashCached()) {
222       clone.hash = hash;
223     }
224     return clone;
225   }
226 
227   @Override
228   public boolean equals(Object thatObject) {
229     if (thatObject == null) {
230       return false;
231     }
232     if (this == thatObject) {
233       return true;
234     }
235     if (hashCode() != thatObject.hashCode()) {
236       return false;
237     }
238     if (!(thatObject instanceof SimpleMutableByteRange)) {
239       return false;
240     }
241     SimpleMutableByteRange that = (SimpleMutableByteRange) thatObject;
242     return Bytes.equals(bytes, offset, length, that.bytes, that.offset, that.length);
243   }
244 
245 }