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 * A basic mutable {@link ByteRange} implementation. 057 */ 058@InterfaceAudience.Public 059public class SimpleMutableByteRange extends AbstractByteRange { 060 061 /** 062 * Create a new {@code ByteRange} lacking a backing array and with an 063 * undefined viewport. 064 */ 065 public SimpleMutableByteRange() { 066 unset(); 067 } 068 069 /** 070 * Create a new {@code ByteRange} over a new backing array of size 071 * {@code capacity}. The range's offset and length are 0 and {@code capacity}, 072 * respectively. 073 * 074 * @param capacity 075 * the size of the backing array. 076 */ 077 public SimpleMutableByteRange(int capacity) { 078 this(new byte[capacity]); 079 } 080 081 /** 082 * Create a new {@code ByteRange} over the provided {@code bytes}. 083 * 084 * @param bytes 085 * The array to wrap. 086 */ 087 public SimpleMutableByteRange(byte[] bytes) { 088 set(bytes); 089 } 090 091 /** 092 * Create a new {@code ByteRange} over the provided {@code bytes}. 093 * 094 * @param bytes 095 * The array to wrap. 096 * @param offset 097 * The offset into {@code bytes} considered the beginning of this 098 * range. 099 * @param length 100 * The length of this range. 101 */ 102 public SimpleMutableByteRange(byte[] bytes, int offset, int length) { 103 set(bytes, offset, length); 104 } 105 106 @Override 107 public ByteRange unset() { 108 clearHashCache(); 109 bytes = null; 110 offset = 0; 111 length = 0; 112 return this; 113 } 114 115 @Override 116 public ByteRange put(int index, byte val) { 117 bytes[offset + index] = val; 118 clearHashCache(); 119 return this; 120 } 121 122 @Override 123 public ByteRange put(int index, byte[] val) { 124 if (0 == val.length) 125 return this; 126 return put(index, val, 0, val.length); 127 } 128 129 @Override 130 public ByteRange put(int index, byte[] val, int offset, int length) { 131 if (0 == length) 132 return this; 133 System.arraycopy(val, offset, this.bytes, this.offset + index, length); 134 clearHashCache(); 135 return this; 136 } 137 138 @Override 139 public ByteRange putShort(int index, short val) { 140 // This writing is same as BB's putShort. When byte[] is wrapped in a BB and 141 // call putShort(), 142 // one can get the same result. 143 bytes[offset + index + 1] = (byte) val; 144 val >>= 8; 145 bytes[offset + index] = (byte) val; 146 clearHashCache(); 147 return this; 148 } 149 150 @Override 151 public ByteRange putInt(int index, int val) { 152 // This writing is same as BB's putInt. When byte[] is wrapped in a BB and 153 // call getInt(), one 154 // can get the same result. 155 for (int i = Bytes.SIZEOF_INT - 1; i > 0; i--) { 156 bytes[offset + index + i] = (byte) val; 157 val >>>= 8; 158 } 159 bytes[offset + index] = (byte) val; 160 clearHashCache(); 161 return this; 162 } 163 164 @Override 165 public ByteRange putLong(int index, long val) { 166 // This writing is same as BB's putLong. When byte[] is wrapped in a BB and 167 // call putLong(), one 168 // can get the same result. 169 for (int i = Bytes.SIZEOF_LONG - 1; i > 0; i--) { 170 bytes[offset + index + i] = (byte) val; 171 val >>>= 8; 172 } 173 bytes[offset + index] = (byte) val; 174 clearHashCache(); 175 return this; 176 } 177 178 // Copied from com.google.protobuf.CodedOutputStream v2.5.0 writeRawVarint64 179 @Override 180 public int putVLong(int index, long val) { 181 int rPos = 0; 182 while (true) { 183 if ((val & ~0x7F) == 0) { 184 bytes[offset + index + rPos] = (byte) val; 185 break; 186 } else { 187 bytes[offset + index + rPos] = (byte) ((val & 0x7F) | 0x80); 188 val >>>= 7; 189 } 190 rPos++; 191 } 192 clearHashCache(); 193 return rPos + 1; 194 } 195 // end copied from protobuf 196 197 @Override 198 public ByteRange deepCopy() { 199 SimpleMutableByteRange clone = new SimpleMutableByteRange(deepCopyToNewArray()); 200 if (isHashCached()) { 201 clone.hash = hash; 202 } 203 return clone; 204 } 205 206 @Override 207 public ByteRange shallowCopy() { 208 SimpleMutableByteRange clone = new SimpleMutableByteRange(bytes, offset, length); 209 if (isHashCached()) { 210 clone.hash = hash; 211 } 212 return clone; 213 } 214 215 @Override 216 public ByteRange shallowCopySubRange(int innerOffset, int copyLength) { 217 SimpleMutableByteRange clone = new SimpleMutableByteRange(bytes, offset + innerOffset, 218 copyLength); 219 if (isHashCached()) { 220 clone.hash = hash; 221 } 222 return clone; 223 } 224 225 @Override 226 public boolean equals(Object thatObject) { 227 if (thatObject == null) { 228 return false; 229 } 230 if (this == thatObject) { 231 return true; 232 } 233 if (hashCode() != thatObject.hashCode()) { 234 return false; 235 } 236 if (!(thatObject instanceof SimpleMutableByteRange)) { 237 return false; 238 } 239 SimpleMutableByteRange that = (SimpleMutableByteRange) thatObject; 240 return Bytes.equals(bytes, offset, length, that.bytes, that.offset, that.length); 241 } 242 243}