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