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 * The portion of this file denoted by 'Copied from com.google.protobuf.CodedOutputStream'
019 * is from Protocol Buffers v2.5.0 under the following license
020 *
021 * Copyright 2008 Google Inc.  All rights reserved.
022 * http://code.google.com/p/protobuf/
023 *
024 * Redistribution and use in source and binary forms, with or without
025 * modification, are permitted provided that the following conditions are
026 * met:
027 *
028 *     * Redistributions of source code must retain the above copyright
029 * notice, this list of conditions and the following disclaimer.
030 *     * Redistributions in binary form must reproduce the above
031 * copyright notice, this list of conditions and the following disclaimer
032 * in the documentation and/or other materials provided with the
033 * distribution.
034 *     * Neither the name of Google Inc. nor the names of its
035 * contributors may be used to endorse or promote products derived from
036 * this software without specific prior written permission.
037 *
038 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
039 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
040 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
041 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
042 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
043 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
044 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
045 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
046 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
047 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
048 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
049 */
050
051package org.apache.hadoop.hbase.util;
052
053import org.apache.yetus.audience.InterfaceAudience;
054
055/**
056 * Extends the basic {@link AbstractPositionedByteRange} implementation with
057 * position support and it is a mutable version. {@code position} is considered transient,
058 * not fundamental to the definition of the range, and does not participate in
059 * {@link #compareTo(ByteRange)}, {@link #hashCode()}, or
060 * {@link #equals(Object)}. {@code Position} is retained by copy operations.
061 */
062@InterfaceAudience.Public
063@edu.umd.cs.findbugs.annotations.SuppressWarnings("EQ_DOESNT_OVERRIDE_EQUALS")
064public class SimplePositionedMutableByteRange extends AbstractPositionedByteRange {
065  /**
066   * Create a new {@code PositionedByteRange} lacking a backing array and with
067   * an undefined viewport.
068   */
069  public SimplePositionedMutableByteRange() {
070    super();
071  }
072
073  /**
074   * Create a new {@code PositionedByteRange} over a new backing array of size
075   * {@code capacity}. The range's offset and length are 0 and {@code capacity},
076   * respectively.
077   * 
078   * @param capacity
079   *          the size of the backing array.
080   */
081  public SimplePositionedMutableByteRange(int capacity) {
082    this(new byte[capacity]);
083  }
084
085  /**
086   * Create a new {@code PositionedByteRange} over the provided {@code bytes}.
087   * 
088   * @param bytes
089   *          The array to wrap.
090   */
091  public SimplePositionedMutableByteRange(byte[] bytes) {
092    set(bytes);
093  }
094
095  /**
096   * Create a new {@code PositionedByteRange} over the provided {@code bytes}.
097   * 
098   * @param bytes
099   *          The array to wrap.
100   * @param offset
101   *          The offset into {@code bytes} considered the beginning of this
102   *          range.
103   * @param length
104   *          The length of this range.
105   */
106  public SimplePositionedMutableByteRange(byte[] bytes, int offset, int length) {
107    set(bytes, offset, length);
108  }
109
110  @Override
111  public PositionedByteRange unset() {
112    this.position = 0;
113    clearHashCache();
114    bytes = null;
115    offset = 0;
116    length = 0;
117    return this;
118  }
119
120  @Override
121  public PositionedByteRange set(int capacity) {
122    this.position = 0;
123    super.set(capacity);
124    this.limit = capacity;
125    return this;
126  }
127
128  @Override
129  public PositionedByteRange set(byte[] bytes) {
130    this.position = 0;
131    super.set(bytes);
132    this.limit = bytes.length;
133    return this;
134  }
135
136  @Override
137  public PositionedByteRange set(byte[] bytes, int offset, int length) {
138    this.position = 0;
139    super.set(bytes, offset, length);
140    limit = length;
141    return this;
142  }
143
144  /**
145   * Update the beginning of this range. {@code offset + length} may not be
146   * greater than {@code bytes.length}. Resets {@code position} to 0.
147   * 
148   * @param offset
149   *          the new start of this range.
150   * @return this.
151   */
152  @Override
153  public PositionedByteRange setOffset(int offset) {
154    this.position = 0;
155    super.setOffset(offset);
156    return this;
157  }
158
159  /**
160   * Update the length of this range. {@code offset + length} should not be
161   * greater than {@code bytes.length}. If {@code position} is greater than the
162   * new {@code length}, sets {@code position} to {@code length}.
163   * 
164   * @param length
165   *          The new length of this range.
166   * @return this.
167   */
168  @Override
169  public PositionedByteRange setLength(int length) {
170    this.position = Math.min(position, length);
171    super.setLength(length);
172    return this;
173  }
174
175  @Override
176  public PositionedByteRange put(byte val) {
177    put(position++, val);
178    return this;
179  }
180
181  @Override
182  public PositionedByteRange put(byte[] val) {
183    if (0 == val.length)
184      return this;
185    return this.put(val, 0, val.length);
186  }
187
188  @Override
189  public PositionedByteRange put(byte[] val, int offset, int length) {
190    if (0 == length)
191      return this;
192    put(position, val, offset, length);
193    this.position += length;
194    return this;
195  }
196
197  @Override
198  public PositionedByteRange get(int index, byte[] dst) {
199    super.get(index, dst);
200    return this;
201  }
202
203  @Override
204  public PositionedByteRange get(int index, byte[] dst, int offset, int length) {
205    super.get(index, dst, offset, length);
206    return this;
207  }
208
209  @Override
210  public PositionedByteRange put(int index, byte val) {
211    bytes[offset + index] = val;
212    return this;
213  }
214
215  @Override
216  public PositionedByteRange put(int index, byte[] val) {
217    if (0 == val.length)
218      return this;
219    return put(index, val, 0, val.length);
220  }
221
222  @Override
223  public PositionedByteRange put(int index, byte[] val, int offset, int length) {
224    if (0 == length)
225      return this;
226    System.arraycopy(val, offset, this.bytes, this.offset + index, length);
227    return this;
228  }
229
230  @Override
231  public PositionedByteRange deepCopy() {
232    SimplePositionedMutableByteRange clone = new SimplePositionedMutableByteRange(
233        deepCopyToNewArray());
234    clone.position = this.position;
235    return clone;
236  }
237
238  @Override
239  public PositionedByteRange shallowCopy() {
240    SimplePositionedMutableByteRange clone = new SimplePositionedMutableByteRange(bytes, offset,
241        length);
242    clone.position = this.position;
243    return clone;
244  }
245
246  @Override
247  public PositionedByteRange shallowCopySubRange(int innerOffset, int copyLength) {
248    SimplePositionedMutableByteRange clone = new SimplePositionedMutableByteRange(bytes, offset
249        + innerOffset, copyLength);
250    clone.position = this.position;
251    return clone;
252  }
253
254  @Override
255  public PositionedByteRange putShort(short val) {
256    putShort(position, val);
257    position += Bytes.SIZEOF_SHORT;
258    return this;
259  }
260
261  @Override
262  public PositionedByteRange putInt(int val) {
263    putInt(position, val);
264    position += Bytes.SIZEOF_INT;
265    return this;
266  }
267
268  @Override
269  public PositionedByteRange putLong(long val) {
270    putLong(position, val);
271    position += Bytes.SIZEOF_LONG;
272    return this;
273  }
274
275  @Override
276  public int putVLong(long val) {
277    int len = putVLong(position, val);
278    position += len;
279    return len;
280  }
281
282  @Override
283  public PositionedByteRange putShort(int index, short val) {
284    // This writing is same as BB's putShort. When byte[] is wrapped in a BB and
285    // call putShort(),
286    // one can get the same result.
287    bytes[offset + index + 1] = (byte) val;
288    val >>= 8;
289    bytes[offset + index] = (byte) val;
290    clearHashCache();
291    return this;
292  }
293
294  @Override
295  public PositionedByteRange putInt(int index, int val) {
296    // This writing is same as BB's putInt. When byte[] is wrapped in a BB and
297    // call getInt(), one
298    // can get the same result.
299    for (int i = Bytes.SIZEOF_INT - 1; i > 0; i--) {
300      bytes[offset + index + i] = (byte) val;
301      val >>>= 8;
302    }
303    bytes[offset + index] = (byte) val;
304    clearHashCache();
305    return this;
306  }
307
308  @Override
309  public PositionedByteRange putLong(int index, long val) {
310    // This writing is same as BB's putLong. When byte[] is wrapped in a BB and
311    // call putLong(), one
312    // can get the same result.
313    for (int i = Bytes.SIZEOF_LONG - 1; i > 0; i--) {
314      bytes[offset + index + i] = (byte) val;
315      val >>>= 8;
316    }
317    bytes[offset + index] = (byte) val;
318    clearHashCache();
319    return this;
320  }
321
322  // Copied from com.google.protobuf.CodedOutputStream v2.5.0 writeRawVarint64
323  @Override
324  public int putVLong(int index, long val) {
325    int rPos = 0;
326    while (true) {
327      if ((val & ~0x7F) == 0) {
328        bytes[offset + index + rPos] = (byte) val;
329        break;
330      } else {
331        bytes[offset + index + rPos] = (byte) ((val & 0x7F) | 0x80);
332        val >>>= 7;
333      }
334      rPos++;
335    }
336    clearHashCache();
337    return rPos + 1;
338  }
339  // end copied from protobuf
340
341}