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// Protocol Buffers - Google's data interchange format 022// Copyright 2008 Google Inc. All rights reserved. 023// https://developers.google.com/protocol-buffers/ 024// 025// Redistribution and use in source and binary forms, with or without 026// modification, are permitted provided that the following conditions are 027// met: 028// 029// * Redistributions of source code must retain the above copyright 030// notice, this list of conditions and the following disclaimer. 031// * Redistributions in binary form must reproduce the above 032// copyright notice, this list of conditions and the following disclaimer 033// in the documentation and/or other materials provided with the 034// distribution. 035// * Neither the name of Google Inc. nor the names of its 036// contributors may be used to endorse or promote products derived from 037// this software without specific prior written permission. 038// 039// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 040// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 041// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 042// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 043// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 044// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 045// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 046// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 047// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 048// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 049// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 050package org.apache.hadoop.hbase.util; 051 052import org.apache.yetus.audience.InterfaceAudience; 053 054/** 055 * A basic mutable {@link ByteRange} implementation. 056 */ 057@InterfaceAudience.Public 058public class SimpleMutableByteRange extends AbstractByteRange { 059 060 /** 061 * Create a new {@code ByteRange} lacking a backing array and with an undefined viewport. 062 */ 063 public SimpleMutableByteRange() { 064 unset(); 065 } 066 067 /** 068 * Create a new {@code ByteRange} over a new backing array of size {@code capacity}. The range's 069 * offset and length are 0 and {@code capacity}, respectively. the size of the backing array. 070 */ 071 public SimpleMutableByteRange(int capacity) { 072 this(new byte[capacity]); 073 } 074 075 /** 076 * Create a new {@code ByteRange} over the provided {@code bytes}. The array to wrap. 077 */ 078 public SimpleMutableByteRange(byte[] bytes) { 079 set(bytes); 080 } 081 082 /** 083 * Create a new {@code ByteRange} over the provided {@code bytes}. The array to wrap. The offset 084 * into {@code bytes} considered the beginning of this range. The length of this range. 085 */ 086 public SimpleMutableByteRange(byte[] bytes, int offset, int length) { 087 set(bytes, offset, length); 088 } 089 090 @Override 091 public ByteRange unset() { 092 clearHashCache(); 093 bytes = null; 094 offset = 0; 095 length = 0; 096 return this; 097 } 098 099 @Override 100 public ByteRange put(int index, byte val) { 101 bytes[offset + index] = val; 102 clearHashCache(); 103 return this; 104 } 105 106 @Override 107 public ByteRange put(int index, byte[] val) { 108 if (0 == val.length) return this; 109 return put(index, val, 0, val.length); 110 } 111 112 @Override 113 public ByteRange put(int index, byte[] val, int offset, int length) { 114 if (0 == length) return this; 115 System.arraycopy(val, offset, this.bytes, this.offset + index, length); 116 clearHashCache(); 117 return this; 118 } 119 120 @Override 121 public ByteRange putShort(int index, short val) { 122 // This writing is same as BB's putShort. When byte[] is wrapped in a BB and 123 // call putShort(), 124 // one can get the same result. 125 bytes[offset + index + 1] = (byte) val; 126 val >>= 8; 127 bytes[offset + index] = (byte) val; 128 clearHashCache(); 129 return this; 130 } 131 132 @Override 133 public ByteRange putInt(int index, int val) { 134 // This writing is same as BB's putInt. When byte[] is wrapped in a BB and 135 // call getInt(), one 136 // can get the same result. 137 for (int i = Bytes.SIZEOF_INT - 1; i > 0; i--) { 138 bytes[offset + index + i] = (byte) val; 139 val >>>= 8; 140 } 141 bytes[offset + index] = (byte) val; 142 clearHashCache(); 143 return this; 144 } 145 146 @Override 147 public ByteRange putLong(int index, long val) { 148 // This writing is same as BB's putLong. When byte[] is wrapped in a BB and 149 // call putLong(), one 150 // can get the same result. 151 for (int i = Bytes.SIZEOF_LONG - 1; i > 0; i--) { 152 bytes[offset + index + i] = (byte) val; 153 val >>>= 8; 154 } 155 bytes[offset + index] = (byte) val; 156 clearHashCache(); 157 return this; 158 } 159 160 // Copied from com.google.protobuf.CodedOutputStream v2.5.0 writeRawVarint64 161 @Override 162 public int putVLong(int index, long val) { 163 int rPos = 0; 164 while (true) { 165 if ((val & ~0x7F) == 0) { 166 bytes[offset + index + rPos] = (byte) val; 167 break; 168 } else { 169 bytes[offset + index + rPos] = (byte) ((val & 0x7F) | 0x80); 170 val >>>= 7; 171 } 172 rPos++; 173 } 174 clearHashCache(); 175 return rPos + 1; 176 } 177 // end copied from protobuf 178 179 @Override 180 public ByteRange deepCopy() { 181 SimpleMutableByteRange clone = new SimpleMutableByteRange(deepCopyToNewArray()); 182 if (isHashCached()) { 183 clone.hash = hash; 184 } 185 return clone; 186 } 187 188 @Override 189 public ByteRange shallowCopy() { 190 SimpleMutableByteRange clone = new SimpleMutableByteRange(bytes, offset, length); 191 if (isHashCached()) { 192 clone.hash = hash; 193 } 194 return clone; 195 } 196 197 @Override 198 public ByteRange shallowCopySubRange(int innerOffset, int copyLength) { 199 SimpleMutableByteRange clone = 200 new SimpleMutableByteRange(bytes, offset + innerOffset, copyLength); 201 if (isHashCached()) { 202 clone.hash = hash; 203 } 204 return clone; 205 } 206 207 @Override 208 public boolean equals(Object thatObject) { 209 if (thatObject == null) { 210 return false; 211 } 212 if (this == thatObject) { 213 return true; 214 } 215 if (hashCode() != thatObject.hashCode()) { 216 return false; 217 } 218 if (!(thatObject instanceof SimpleMutableByteRange)) { 219 return false; 220 } 221 SimpleMutableByteRange that = (SimpleMutableByteRange) thatObject; 222 return Bytes.equals(bytes, offset, length, that.bytes, that.offset, that.length); 223 } 224 225}