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 020 021import org.apache.yetus.audience.InterfaceAudience; 022import org.apache.yetus.audience.InterfaceStability; 023 024import org.apache.hbase.thirdparty.com.google.common.annotations.VisibleForTesting; 025 026/** 027 * Extends the basic {@link SimpleByteRange} implementation with position 028 * support. {@code position} is considered transient, not fundamental to the 029 * definition of the range, and does not participate in 030 * {@link #compareTo(ByteRange)}, {@link #hashCode()}, or 031 * {@link #equals(Object)}. {@code Position} is retained by copy operations. 032 */ 033@InterfaceAudience.Private 034@InterfaceStability.Evolving 035public abstract class AbstractPositionedByteRange extends AbstractByteRange implements 036 PositionedByteRange { 037 /** 038 * The current index into the range. Like {@link java.nio.ByteBuffer} position, it 039 * points to the next value that will be read/written in the array. It 040 * provides the appearance of being 0-indexed, even though its value is 041 * calculated according to offset. 042 * <p> 043 * Position is considered transient and does not participate in 044 * {@link #equals(Object)} or {@link #hashCode()} comparisons. 045 * </p> 046 */ 047 protected int position = 0; 048 049 protected int limit = 0; 050 051 @Override 052 public abstract PositionedByteRange unset(); 053 054 @Override 055 public PositionedByteRange set(int capacity) { 056 this.position = 0; 057 super.set(capacity); 058 this.limit = capacity; 059 return this; 060 } 061 062 @Override 063 public PositionedByteRange set(byte[] bytes) { 064 this.position = 0; 065 super.set(bytes); 066 this.limit = bytes.length; 067 return this; 068 } 069 070 @Override 071 public PositionedByteRange set(byte[] bytes, int offset, int length) { 072 this.position = 0; 073 super.set(bytes, offset, length); 074 limit = length; 075 return this; 076 } 077 078 /** 079 * Update the beginning of this range. {@code offset + length} may not be 080 * greater than {@code bytes.length}. Resets {@code position} to 0. 081 * 082 * @param offset 083 * the new start of this range. 084 * @return this. 085 */ 086 @Override 087 public PositionedByteRange setOffset(int offset) { 088 this.position = 0; 089 super.setOffset(offset); 090 return this; 091 } 092 093 /** 094 * Update the length of this range. {@code offset + length} should not be 095 * greater than {@code bytes.length}. If {@code position} is greater than the 096 * new {@code length}, sets {@code position} to {@code length}. 097 * 098 * @param length 099 * The new length of this range. 100 * @return this. 101 */ 102 @Override 103 public PositionedByteRange setLength(int length) { 104 this.position = Math.min(position, length); 105 super.setLength(length); 106 return this; 107 } 108 109 @Override 110 public int getPosition() { 111 return position; 112 } 113 114 @Override 115 public PositionedByteRange setPosition(int position) { 116 this.position = position; 117 return this; 118 } 119 120 @Override 121 public int getRemaining() { 122 return length - position; 123 } 124 125 @Override 126 public byte peek() { 127 return bytes[offset + position]; 128 } 129 130 @Override 131 public byte get() { 132 return get(position++); 133 } 134 135 @Override 136 public PositionedByteRange get(byte[] dst) { 137 if (0 == dst.length) 138 return this; 139 return this.get(dst, 0, dst.length); // be clear we're calling self, not 140 // super 141 } 142 143 @Override 144 public PositionedByteRange get(byte[] dst, int offset, int length) { 145 if (0 == length) 146 return this; 147 super.get(this.position, dst, offset, length); 148 this.position += length; 149 return this; 150 } 151 152 @Override 153 public abstract PositionedByteRange put(byte val); 154 155 @Override 156 public abstract PositionedByteRange put(byte[] val); 157 158 @Override 159 public abstract PositionedByteRange put(byte[] val, int offset, int length); 160 161 @Override 162 public abstract PositionedByteRange putInt(int index, int val); 163 164 @Override 165 public abstract PositionedByteRange putLong(int index, long val); 166 167 @Override 168 public abstract PositionedByteRange putShort(int index, short val); 169 170 @Override 171 public abstract PositionedByteRange putInt(int val); 172 173 @Override 174 public abstract PositionedByteRange putLong(long val); 175 176 @Override 177 public abstract PositionedByteRange putShort(short val); 178 179 @Override 180 public abstract int putVLong(int index, long val); 181 182 @Override 183 public abstract int putVLong(long val); 184 /** 185 * Similar to {@link java.nio.ByteBuffer#flip()}. Sets length to position, position to 186 * offset. 187 */ 188 @VisibleForTesting 189 PositionedByteRange flip() { 190 clearHashCache(); 191 length = position; 192 position = offset; 193 return this; 194 } 195 196 /** 197 * Similar to {@link java.nio.ByteBuffer#clear()}. Sets position to 0, length to 198 * capacity. 199 */ 200 @VisibleForTesting 201 PositionedByteRange clear() { 202 clearHashCache(); 203 position = 0; 204 length = bytes.length - offset; 205 return this; 206 } 207 208 // java boilerplate 209 210 @Override 211 public PositionedByteRange get(int index, byte[] dst) { 212 super.get(index, dst); 213 return this; 214 } 215 216 @Override 217 public PositionedByteRange get(int index, byte[] dst, int offset, int length) { 218 super.get(index, dst, offset, length); 219 return this; 220 } 221 222 @Override 223 public short getShort() { 224 short s = getShort(position); 225 position += Bytes.SIZEOF_SHORT; 226 return s; 227 } 228 229 @Override 230 public int getInt() { 231 int i = getInt(position); 232 position += Bytes.SIZEOF_INT; 233 return i; 234 } 235 236 @Override 237 public long getLong() { 238 long l = getLong(position); 239 position += Bytes.SIZEOF_LONG; 240 return l; 241 } 242 243 @Override 244 public long getVLong() { 245 long p = getVLong(position); 246 position += getVLongSize(p); 247 return p; 248 } 249 250 @Override 251 public abstract PositionedByteRange put(int index, byte val); 252 253 @Override 254 public abstract PositionedByteRange put(int index, byte[] val); 255 256 @Override 257 public abstract PositionedByteRange put(int index, byte[] val, int offset, int length); 258 259 @Override 260 public abstract PositionedByteRange deepCopy(); 261 262 @Override 263 public abstract PositionedByteRange shallowCopy(); 264 265 @Override 266 public abstract PositionedByteRange shallowCopySubRange(int innerOffset, int copyLength); 267 268 @Override 269 public PositionedByteRange setLimit(int limit) { 270 this.limit = limit; 271 return this; 272 } 273 274 @Override 275 public int getLimit() { 276 return this.limit; 277 } 278}