1<?php 2 3declare(strict_types=1); 4 5/* 6 * This file is part of the TYPO3 CMS project. 7 * 8 * It is free software; you can redistribute it and/or modify it under 9 * the terms of the GNU General Public License, either version 2 10 * of the License, or any later version. 11 * 12 * For the full copyright and license information, please read the 13 * LICENSE.txt file that was distributed with this source code. 14 * 15 * The TYPO3 project - inspiring people to share! 16 */ 17 18namespace TYPO3\CMS\Core\Type; 19 20/** 21 * The BitSet class is a helper class to manage bit sets. It eases the work with bits and bitwise 22 * operations by providing a reliable and tested API. 23 * 24 * The class can be used standalone or as a parent for more verbose classes that handle bit sets. 25 * 26 * 27 * The functionality is best described by an example: 28 * 29 * define('PERMISSIONS_NONE', 0b0); // 0 30 * define('PERMISSIONS_PAGE_SHOW', 0b1); // 1 31 * define('PERMISSIONS_PAGE_EDIT', 0b10); // 2 32 * define('PERMISSIONS_PAGE_DELETE', 0b100); // 4 33 * 34 * $bitSet = new \TYPO3\CMS\Core\Type\BitSet(PERMISSIONS_PAGE_SHOW | PERMISSIONS_PAGE_EDIT); 35 * $bitSet->get(PERMISSIONS_PAGE_SHOW); // true 36 * $bitSet->get(PERMISSIONS_PAGE_DELETE); // false 37 * 38 * Another example shows how to possibly extend the class: 39 * 40 * class Permissions extends \TYPO3\CMS\Core\Type\BitSet 41 * { 42 * public const NONE = 0b0; // 0 43 * public const PAGE_SHOW = 0b1; // 1 44 * 45 * public function isGranted(int $permission): bool 46 * { 47 * return $this->get($permission); 48 * } 49 * 50 * public function grant(int $permission): void 51 * { 52 * $this->set($permission); 53 * } 54 * } 55 * 56 * $permissions = new Permissions(); 57 * $permissions->isGranted(Permissions::PAGE_SHOW); // false 58 * $permissions->grant(Permissions::PAGE_SHOW); 59 * $permissions->isGranted(Permissions::PAGE_SHOW); // true 60 */ 61class BitSet 62{ 63 /** 64 * @var int 65 */ 66 private $set; 67 68 /** 69 * @param int $set 70 */ 71 public function __construct(int $set = 0) 72 { 73 $this->set = $set; 74 } 75 76 /** 77 * Performs the same operation as {@see or()} without the need to create a BitSet instance from 78 * an integer value. 79 * 80 * @param int $bitIndex 81 */ 82 public function set(int $bitIndex): void 83 { 84 $this->set |= $bitIndex; 85 } 86 87 /** 88 * @param int $bitIndex 89 * @param bool $value 90 */ 91 public function setValue(int $bitIndex, bool $value): void 92 { 93 if ($value) { 94 $this->set($bitIndex); 95 } else { 96 $this->unset($bitIndex); 97 } 98 } 99 100 /** 101 * Performs the same operation as {@see andNot()} without the need to create a BitSet instance from 102 * an integer value. 103 * 104 * @param int $bitIndex 105 */ 106 public function unset(int $bitIndex): void 107 { 108 $this->set &= ~$bitIndex; 109 } 110 111 /** 112 * @param int $bitIndex 113 * @return bool 114 */ 115 public function get(int $bitIndex): bool 116 { 117 return ($bitIndex & $this->set) === $bitIndex; 118 } 119 120 /** 121 * Sets all of the bits in this BitSet to false. 122 */ 123 public function clear(): void 124 { 125 $this->set = 0; 126 } 127 128 /** 129 * Performs a logical AND of this target bit set with the argument bit set. This bit set is 130 * modified so that each bit in it has the value true if and only if it both initially had the 131 * value true and the corresponding bit in the bit set argument also had the value true. 132 * 133 * @param BitSet $set 134 */ 135 public function and(BitSet $set): void 136 { 137 $this->set &= $set->__toInt(); 138 } 139 140 /** 141 * Performs a logical OR of this bit set with the bit set argument. This bit set is modified so 142 * that a bit in it has the value true if and only if it either already had the value true or 143 * the corresponding bit in the bit set argument has the value true. 144 * 145 * @param BitSet $set 146 */ 147 public function or(BitSet $set): void 148 { 149 $this->set |= $set->__toInt(); 150 } 151 152 /** 153 * Performs a logical XOR of this bit set with the bit set argument. This bit set is modified so 154 * that a bit in it has the value true if and only if one of the following statements holds: 155 * 156 * - The bit initially has the value true, and the corresponding bit 157 * in the argument has the value false. 158 * - The bit initially has the value false, and the corresponding bit 159 * in the argument has the value true. 160 * 161 * @param BitSet $set 162 */ 163 public function xor(BitSet $set): void 164 { 165 $this->set ^= $set->__toInt(); 166 } 167 168 /** 169 * Clears all of the bits in this BitSet whose corresponding bit is set in the specified BitSet. 170 * 171 * @param BitSet $set 172 */ 173 public function andNot(BitSet $set): void 174 { 175 $this->set &= ~$set->__toInt(); 176 } 177 178 /** 179 * Returns the integer representation of the internal set. 180 * (As PHP does not know a byte type, the internal set is already handled as an integer and can 181 * therefore directly be returned) 182 * 183 * @return int 184 */ 185 public function __toInt(): int 186 { 187 return $this->set; 188 } 189 190 /** 191 * Returns the (binary) string representation of the internal (integer) set. 192 * 193 * @return string 194 */ 195 public function __toString(): string 196 { 197 return '0b' . decbin($this->set); 198 } 199} 200