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}