001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * https://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018package org.apache.commons.lang3; 019 020/** 021 * Supports operations on bit-mapped fields. Instances of this class can be used to store a flag or data within an {@code int}, {@code short} or {@code byte}. 022 * <p> 023 * Each {@link BitField} is constructed with a mask value, which indicates the bits that will be used to store and retrieve the data for that field. For 024 * instance, the mask {@code 0xFF} indicates the least-significant byte should be used to store the data. 025 * </p> 026 * <p> 027 * As an example, consider a car painting machine that accepts paint instructions as integers. Bit fields can be used to encode this: 028 * </p> 029 * 030 * <pre> 031 * 032 * // blue, green and red are 1 byte values (0-255) stored in the three least 033 * // significant bytes 034 * BitField blue = new BitField(0xFF); 035 * 036 * BitField green = new BitField(0xFF00); 037 * 038 * BitField red = new BitField(0xFF0000); 039 * 040 * // anyColor is a flag triggered if any color is used 041 * BitField anyColor = new BitField(0xFFFFFF); 042 * 043 * // isMetallic is a single bit flag 044 * BitField isMetallic = new BitField(0x1000000); 045 * </pre> 046 * <p> 047 * Using these {@link BitField} instances, a paint instruction can be encoded into an integer: 048 * </p> 049 * 050 * <pre> 051 * int paintInstruction = 0; 052 * paintInstruction = red.setValue(paintInstruction, 35); 053 * paintInstruction = green.setValue(paintInstruction, 100); 054 * paintInstruction = blue.setValue(paintInstruction, 255); 055 * </pre> 056 * <p> 057 * Flags and data can be retrieved from the integer: 058 * </p> 059 * 060 * <pre> 061 * // Prints true if red, green or blue is non-zero 062 * System.out.println(anyColor.isSet(paintInstruction)); // prints true 063 * // Prints value of red, green and blue 064 * System.out.println(red.getValue(paintInstruction)); // prints 35 065 * System.out.println(green.getValue(paintInstruction)); // prints 100 066 * System.out.println(blue.getValue(paintInstruction)); // prints 255 067 * // Prints true if isMetallic was set 068 * System.out.println(isMetallic.isSet(paintInstruction)); // prints false 069 * </pre> 070 * 071 * @since 2.0 072 */ 073public class BitField { 074 075 private final long mask; 076 077 private final int shiftCount; 078 079 /** 080 * Creates a BitField instance. 081 * 082 * @param mask The mask specifying which bits apply to this BitField. Bits that are set in this mask are the bits that this BitField operates on. 083 */ 084 public BitField(final int mask) { 085 this.mask = Integer.toUnsignedLong(mask); 086 this.shiftCount = this.mask == 0 ? 0 : Long.numberOfTrailingZeros(this.mask); 087 } 088 089 /** 090 * Creates a BitField instance. 091 * <p> 092 * If any bit above bit 31 is set in the mask, the resulting field can only be used with the {@code long} holder accessors; the {@code int}, {@code short} 093 * and {@code byte} holder accessors throw {@link IllegalStateException} for such a field, because those holder types cannot contain the masked bits and 094 * would otherwise silently answer wrongly (shift counts are truncated mod 32 and negative holders are sign-extended into bits 32-63). 095 * </p> 096 * 097 * @param mask The mask specifying which bits apply to this BitField. Bits that are set in this mask are the bits that this BitField operates on. 098 * @since 3.21.0 099 */ 100 public BitField(final long mask) { 101 this.mask = mask; 102 this.shiftCount = mask == 0 ? 0 : Long.numberOfTrailingZeros(mask); 103 } 104 105 /** 106 * Clears the bits. 107 * 108 * @param holder The int data containing the bits we're interested in. 109 * @return The value of holder with the specified bits cleared (set to {@code 0}). 110 * @throws IllegalStateException Thrown if this field's mask has bits set above bit 31 (only possible via {@link #BitField(long)}) and so cannot be 111 * represented in this holder type. 112 */ 113 public int clear(final int holder) { 114 return (int) (holder & ~intMask()); 115 } 116 117 /** 118 * Clears the bits. 119 * 120 * @param holder The long data containing the bits we're interested in. 121 * @return The value of holder with the specified bits cleared (set to {@code 0}). 122 * @since 3.21.0 123 */ 124 public long clear(final long holder) { 125 return holder & ~mask; 126 } 127 128 /** 129 * Clears the bits. 130 * 131 * @param holder The byte data containing the bits we're interested in. 132 * @return The value of holder with the specified bits cleared (set to {@code 0}). 133 * @throws IllegalStateException Thrown if this field's mask has bits set above bit 31 (only possible via {@link #BitField(long)}) and so cannot be 134 * represented in this holder type. 135 */ 136 public byte clearByte(final byte holder) { 137 return (byte) clear(holder); 138 } 139 140 /** 141 * Clears the bits. 142 * 143 * @param holder The short data containing the bits we're interested in. 144 * @return The value of holder with the specified bits cleared (set to {@code 0}). 145 * @throws IllegalStateException Thrown if this field's mask has bits set above bit 31 (only possible via {@link #BitField(long)}) and so cannot be 146 * represented in this holder type. 147 */ 148 public short clearShort(final short holder) { 149 return (short) clear(holder); 150 } 151 152 /** 153 * Gets the value for the specified BitField, unshifted. 154 * 155 * @param holder The int data containing the bits we're interested in. 156 * @return The selected bits. 157 * @throws IllegalStateException Thrown if this field's mask has bits set above bit 31 (only possible via {@link #BitField(long)}) and so cannot be 158 * represented in this holder type. 159 */ 160 public int getRawValue(final int holder) { 161 return (int) (holder & intMask()); 162 } 163 164 /** 165 * Gets the value for the specified BitField, unshifted. 166 * 167 * @param holder The long data containing the bits we're interested in. 168 * @return The selected bits. 169 * @since 3.21.0 170 */ 171 public long getRawValue(final long holder) { 172 return holder & mask; 173 } 174 175 /** 176 * Gets the value for the specified BitField, unshifted. 177 * 178 * @param holder The short data containing the bits we're interested in. 179 * @return The selected bits. 180 * @throws IllegalStateException Thrown if this field's mask has bits set above bit 31 (only possible via {@link #BitField(long)}) and so cannot be 181 * represented in this holder type. 182 */ 183 public short getShortRawValue(final short holder) { 184 return (short) getRawValue(holder); 185 } 186 187 /** 188 * Gets the value for the specified BitField, appropriately shifted right, as a short. 189 * <p> 190 * Many users of a BitField will want to treat the specified bits as an int value, and will not want to be aware that the value is stored as a BitField (and 191 * so shifted left so many bits). 192 * </p> 193 * 194 * @param holder The short data containing the bits we're interested in. 195 * @return The selected bits, shifted right appropriately. 196 * @see #setShortValue(short,short) 197 * @throws IllegalStateException Thrown if this field's mask has bits set above bit 31 (only possible via {@link #BitField(long)}) and so cannot be 198 * represented in this holder type. 199 */ 200 public short getShortValue(final short holder) { 201 return (short) getValue(holder); 202 } 203 204 /** 205 * Gets the value for the specified BitField, appropriately shifted right. 206 * <p> 207 * Many users of a BitField will want to treat the specified bits as an int value, and will not want to be aware that the value is stored as a BitField (and 208 * so shifted left so many bits). 209 * </p> 210 * 211 * @param holder The int data containing the bits we're interested in. 212 * @return The selected bits, shifted right appropriately. 213 * @see #setValue(int,int) 214 * @throws IllegalStateException Thrown if this field's mask has bits set above bit 31 (only possible via {@link #BitField(long)}) and so cannot be 215 * represented in this holder type. 216 */ 217 public int getValue(final int holder) { 218 return getRawValue(holder) >>> shiftCount; 219 } 220 221 /** 222 * Gets the value for the specified BitField, appropriately shifted right. 223 * <p> 224 * Many users of a BitField will want to treat the specified bits as an long value, and will not want to be aware that the value is stored as a BitField (and 225 * so shifted left so many bits). 226 * </p> 227 * 228 * @param holder The long data containing the bits we're interested in. 229 * @return The selected bits, shifted right appropriately. 230 * @see #setValue(long,long) 231 * @since 3.21.0 232 */ 233 public long getValue(final long holder) { 234 return getRawValue(holder) >>> shiftCount; 235 } 236 237 /** 238 * Verifies that this field's mask fits in an {@code int} holder before an {@code int}, {@code short} or {@code byte} accessor uses it. 239 * <p> 240 * Without this check, a mask with bits above bit 31 makes the narrow accessors silently wrong: the {@code int} shift count is truncated mod 32, and a 241 * negative narrow holder is sign-extended to 64 bits before the {@code long} mask is applied, reporting above-bit-31 flags as set even though the holder 242 * type cannot contain them. 243 * </p> 244 * 245 * @return the mask, guaranteed to fit in 32 bits. 246 * @throws IllegalStateException Thrown if the mask has bits set above bit 31. 247 */ 248 private long intMask() { 249 if (mask >>> Integer.SIZE != 0) { 250 throw new IllegalStateException("BitField mask 0x" + Long.toHexString(mask) + " exceeds 32 bits; use the long accessors for this field."); 251 } 252 return mask; 253 } 254 255 /** 256 * Tests whether all of the bits are set or not. 257 * <p> 258 * This is a stricter test than {@link #isSet(int)}, in that all of the bits in a multi-bit set must be set for this method to return {@code true}. 259 * </p> 260 * 261 * @param holder The int data containing the bits we're interested in. 262 * @return {@code true} if all of the bits are set, else {@code false}. 263 * @throws IllegalStateException Thrown if this field's mask has bits set above bit 31 (only possible via {@link #BitField(long)}) and so cannot be 264 * represented in this holder type. 265 */ 266 public boolean isAllSet(final int holder) { 267 final long intMask = intMask(); 268 return (holder & intMask) == intMask; 269 } 270 271 /** 272 * Tests whether all of the bits are set or not. 273 * <p> 274 * This is a stricter test than {@link #isSet(long)}, in that all of the bits in a multi-bit set must be set for this method to return {@code true}. 275 * </p> 276 * 277 * @param holder The long data containing the bits we're interested in. 278 * @return {@code true} if all of the bits are set, else {@code false}. 279 * @since 3.21.0 280 */ 281 public boolean isAllSet(final long holder) { 282 return (holder & mask) == mask; 283 } 284 285 /** 286 * Tests whether the field is set or not. 287 * <p> 288 * This is most commonly used for a single-bit field, which is often used to represent a boolean value; the results of using it for a multi-bit field is to 289 * determine whether <em>any</em> of its bits are set. 290 * </p> 291 * 292 * @param holder The int data containing the bits we're interested in 293 * @return {@code true} if any of the bits are set, else {@code false} 294 * @throws IllegalStateException Thrown if this field's mask has bits set above bit 31 (only possible via {@link #BitField(long)}) and so cannot be 295 * represented in this holder type. 296 */ 297 public boolean isSet(final int holder) { 298 return (holder & intMask()) != 0; 299 } 300 301 /** 302 * Tests whether the field is set or not. 303 * <p> 304 * This is most commonly used for a single-bit field, which is often used to represent a boolean value; the results of using it for a multi-bit field is to 305 * determine whether <em>any</em> of its bits are set. 306 * </p> 307 * 308 * @param holder The long data containing the bits we're interested in 309 * @return {@code true} if any of the bits are set, else {@code false} 310 * @since 3.21.0 311 */ 312 public boolean isSet(final long holder) { 313 return (holder & mask) != 0; 314 } 315 316 /** 317 * Sets the bits. 318 * 319 * @param holder The int data containing the bits we're interested in. 320 * @return The value of holder with the specified bits set to {@code 1}. 321 * @throws IllegalStateException Thrown if this field's mask has bits set above bit 31 (only possible via {@link #BitField(long)}) and so cannot be 322 * represented in this holder type. 323 */ 324 public int set(final int holder) { 325 return (int) (holder | intMask()); 326 } 327 328 /** 329 * Sets the bits. 330 * 331 * @param holder The long data containing the bits we're interested in. 332 * @return The value of holder with the specified bits set to {@code 1}. 333 * @since 3.21.0 334 */ 335 public long set(final long holder) { 336 return holder | mask; 337 } 338 339 /** 340 * Sets a boolean BitField. 341 * 342 * @param holder The int data containing the bits we're interested in. 343 * @param flag indicating whether to set or clear the bits. 344 * @return The value of holder with the specified bits set or cleared. 345 * @throws IllegalStateException Thrown if this field's mask has bits set above bit 31 (only possible via {@link #BitField(long)}) and so cannot be 346 * represented in this holder type. 347 */ 348 public int setBoolean(final int holder, final boolean flag) { 349 return flag ? set(holder) : clear(holder); 350 } 351 352 /** 353 * Sets a boolean BitField. 354 * 355 * @param holder The long data containing the bits we're interested in. 356 * @param flag indicating whether to set or clear the bits. 357 * @return The value of holder with the specified bits set or cleared. 358 * @since 3.21.0 359 */ 360 public long setBoolean(final long holder, final boolean flag) { 361 return flag ? set(holder) : clear(holder); 362 } 363 364 /** 365 * Sets the bits. 366 * 367 * @param holder The byte data containing the bits we're interested in 368 * @return The value of holder with the specified bits set to {@code 1} 369 * @throws IllegalStateException Thrown if this field's mask has bits set above bit 31 (only possible via {@link #BitField(long)}) and so cannot be 370 * represented in this holder type. 371 */ 372 public byte setByte(final byte holder) { 373 return (byte) set(holder); 374 } 375 376 /** 377 * Sets a boolean BitField. 378 * 379 * @param holder The byte data containing the bits we're interested in. 380 * @param flag indicating whether to set or clear the bits. 381 * @return The value of holder with the specified bits set or cleared. 382 * @throws IllegalStateException Thrown if this field's mask has bits set above bit 31 (only possible via {@link #BitField(long)}) and so cannot be 383 * represented in this holder type. 384 */ 385 public byte setByteBoolean(final byte holder, final boolean flag) { 386 return flag ? setByte(holder) : clearByte(holder); 387 } 388 389 /** 390 * Sets the bits. 391 * 392 * @param holder The short data containing the bits we're interested in. 393 * @return The value of holder with the specified bits set to {@code 1}. 394 * @throws IllegalStateException Thrown if this field's mask has bits set above bit 31 (only possible via {@link #BitField(long)}) and so cannot be 395 * represented in this holder type. 396 */ 397 public short setShort(final short holder) { 398 return (short) set(holder); 399 } 400 401 /** 402 * Sets a boolean BitField. 403 * 404 * @param holder The short data containing the bits we're interested in. 405 * @param flag indicating whether to set or clear the bits. 406 * @return The value of holder with the specified bits set or cleared. 407 * @throws IllegalStateException Thrown if this field's mask has bits set above bit 31 (only possible via {@link #BitField(long)}) and so cannot be 408 * represented in this holder type. 409 */ 410 public short setShortBoolean(final short holder, final boolean flag) { 411 return flag ? setShort(holder) : clearShort(holder); 412 } 413 414 /** 415 * Sets the bits with new values. 416 * 417 * @param holder The short data containing the bits we're interested in 418 * @param value The new value for the specified bits 419 * @return The value of holder with the bits from the value parameter replacing the old bits 420 * @see #getShortValue(short) 421 * @throws IllegalStateException Thrown if this field's mask has bits set above bit 31 (only possible via {@link #BitField(long)}) and so cannot be 422 * represented in this holder type. 423 */ 424 public short setShortValue(final short holder, final short value) { 425 return (short) setValue(holder, value); 426 } 427 428 /** 429 * Sets the bits with new values. 430 * 431 * @param holder The int data containing the bits we're interested in. 432 * @param value The new value for the specified bits. 433 * @return The value of holder with the bits from the value parameter replacing the old bits. 434 * @see #getValue(int) 435 * @throws IllegalStateException Thrown if this field's mask has bits set above bit 31 (only possible via {@link #BitField(long)}) and so cannot be 436 * represented in this holder type. 437 */ 438 public int setValue(final int holder, final int value) { 439 final long intMask = intMask(); 440 return (int) (holder & ~intMask | value << shiftCount & intMask); 441 } 442 443 /** 444 * Sets the bits with new values. 445 * 446 * @param holder The long data containing the bits we're interested in. 447 * @param value The new value for the specified bits. 448 * @return The value of holder with the bits from the value parameter replacing the old bits. 449 * @see #getValue(long) 450 * @since 3.21.0 451 */ 452 public long setValue(final long holder, final long value) { 453 return holder & ~mask | value << shiftCount & mask; 454 } 455}