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 */
018package org.apache.hadoop.hbase.util;
019
020import org.apache.yetus.audience.InterfaceAudience;
021import org.apache.yetus.audience.InterfaceStability;
022
023/**
024 * Extends the basic {@link SimpleByteRange} implementation with position
025 * support. {@code position} is considered transient, not fundamental to the
026 * definition of the range, and does not participate in
027 * {@link #compareTo(ByteRange)}, {@link #hashCode()}, or
028 * {@link #equals(Object)}. {@code Position} is retained by copy operations.
029 */
030@InterfaceAudience.Private
031@InterfaceStability.Evolving
032public abstract class AbstractPositionedByteRange extends AbstractByteRange implements
033    PositionedByteRange {
034  /**
035   * The current index into the range. Like {@link java.nio.ByteBuffer} position, it
036   * points to the next value that will be read/written in the array. It
037   * provides the appearance of being 0-indexed, even though its value is
038   * calculated according to offset.
039   * <p>
040   * Position is considered transient and does not participate in
041   * {@link #equals(Object)} or {@link #hashCode()} comparisons.
042   * </p>
043   */
044  protected int position = 0;
045
046  protected int limit = 0;
047
048  @Override
049  public PositionedByteRange set(int capacity) {
050    this.position = 0;
051    super.set(capacity);
052    this.limit = capacity;
053    return this;
054  }
055
056  @Override
057  public PositionedByteRange set(byte[] bytes) {
058    this.position = 0;
059    super.set(bytes);
060    this.limit = bytes.length;
061    return this;
062  }
063
064  @Override
065  public PositionedByteRange set(byte[] bytes, int offset, int length) {
066    this.position = 0;
067    super.set(bytes, offset, length);
068    limit = length;
069    return this;
070  }
071
072  /**
073   * Update the beginning of this range. {@code offset + length} may not be
074   * greater than {@code bytes.length}. Resets {@code position} to 0.
075   *
076   * @param offset
077   *          the new start of this range.
078   * @return this.
079   */
080  @Override
081  public PositionedByteRange setOffset(int offset) {
082    this.position = 0;
083    super.setOffset(offset);
084    return this;
085  }
086
087  /**
088   * Update the length of this range. {@code offset + length} should not be
089   * greater than {@code bytes.length}. If {@code position} is greater than the
090   * new {@code length}, sets {@code position} to {@code length}.
091   *
092   * @param length
093   *          The new length of this range.
094   * @return this.
095   */
096  @Override
097  public PositionedByteRange setLength(int length) {
098    this.position = Math.min(position, length);
099    super.setLength(length);
100    return this;
101  }
102
103  @Override
104  public int getPosition() {
105    return position;
106  }
107
108  @Override
109  public PositionedByteRange setPosition(int position) {
110    this.position = position;
111    return this;
112  }
113
114  @Override
115  public int getRemaining() {
116    return length - position;
117  }
118
119  @Override
120  public byte peek() {
121    return bytes[offset + position];
122  }
123
124  @Override
125  public byte get() {
126    return get(position++);
127  }
128
129  @Override
130  public PositionedByteRange get(byte[] dst) {
131    if (0 == dst.length) {
132      return this;
133    }
134
135    return this.get(dst, 0, dst.length); // be clear we're calling self, not super
136  }
137
138  @Override
139  public PositionedByteRange get(byte[] dst, int offset, int length) {
140    if (0 == length) {
141      return this;
142    }
143
144    super.get(this.position, dst, offset, length);
145    this.position += length;
146    return this;
147  }
148
149  // java boilerplate
150
151  @Override
152  public PositionedByteRange get(int index, byte[] dst) {
153    super.get(index, dst);
154    return this;
155  }
156
157  @Override
158  public PositionedByteRange get(int index, byte[] dst, int offset, int length) {
159    super.get(index, dst, offset, length);
160    return this;
161  }
162
163  @Override
164  public short getShort() {
165    short s = getShort(position);
166    position += Bytes.SIZEOF_SHORT;
167    return s;
168  }
169
170  @Override
171  public int getInt() {
172    int i = getInt(position);
173    position += Bytes.SIZEOF_INT;
174    return i;
175  }
176
177  @Override
178  public long getLong() {
179    long l = getLong(position);
180    position += Bytes.SIZEOF_LONG;
181    return l;
182  }
183
184  @Override
185  public long getVLong() {
186    long p = getVLong(position);
187    position += getVLongSize(p);
188    return p;
189  }
190
191  @Override
192  public PositionedByteRange setLimit(int limit) {
193    this.limit = limit;
194    return this;
195  }
196
197  @Override
198  public int getLimit() {
199    return this.limit;
200  }
201}