Skip to content

Commit

Permalink
[FEATURE] Introduce BitSet class
Browse files Browse the repository at this point in the history
This patch introduces a simple BitSet class that
can be used to handle boolean flags.

Releases: master
Resolves: #87665
Change-Id: I32911ed1213421ef30596c2aceb4b8cbd27a8a45
Reviewed-on: https://review.typo3.org/c/59650
Tested-by: TYPO3com <noreply@typo3.com>
Tested-by: Susanne Moog <susanne.moog@typo3.org>
Tested-by: Andreas Fernandez <a.fernandez@scripting-base.de>
Tested-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
Reviewed-by: Oliver Klee <typo3-coding@oliverklee.de>
Reviewed-by: Susanne Moog <susanne.moog@typo3.org>
Reviewed-by: Andreas Fernandez <a.fernandez@scripting-base.de>
Reviewed-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
  • Loading branch information
alexanderschnitzler authored and maddy2101 committed Feb 23, 2019
1 parent 9116fcd commit 81ddfe4
Show file tree
Hide file tree
Showing 3 changed files with 249 additions and 0 deletions.
74 changes: 74 additions & 0 deletions typo3/sysext/core/Classes/DataStructure/BitSet.php
@@ -0,0 +1,74 @@
<?php
declare(strict_types = 1);

/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/

namespace TYPO3\CMS\Core\DataStructure;

/**
* Class TYPO3\CMS\Core\DataStructure\BitSet
*/
class BitSet
{
/**
* @var int
*/
private $set;

/**
* @param int $set
*/
public function __construct(int $set = 0)
{
$this->set = $set;
}

/**
* @param int $bitIndex
*/
public function set(int $bitIndex): void
{
$this->set |= $bitIndex;
}

/**
* @param int $bitIndex
* @param bool $value
*/
public function setValue(int $bitIndex, bool $value): void
{
if ($value) {
$this->set($bitIndex);
} else {
$this->unset($bitIndex);
}
}

/**
* @param int $bitIndex
*/
public function unset(int $bitIndex): void
{
$this->set &= ~$bitIndex;
}

/**
* @param int $bitIndex
* @return bool
*/
public function get(int $bitIndex): bool
{
return ($bitIndex & $this->set) === $bitIndex;
}
}
@@ -0,0 +1,87 @@
.. include:: ../../Includes.txt

========================================
Feature: #87665 - Introduce BitSet class
========================================

See :issue:`87665`

Description
===========

To efficiently handle boolean flags, bit sets can be used. Therefore a new class :php:`\TYPO3\CMS\Core\DataStructure\BitSet` has been introduced.
The bit set can be used standalone and accessed from the outside but it can also be used to create specific BitSet classes that extend the BitSet class.

The functionality is best described by an example:

::

<?php
declare(strict_types = 1);

define('PERMISSIONS_NONE', 0b0); // 0
define('PERMISSIONS_PAGE_SHOW', 0b1); // 1
define('PERMISSIONS_PAGE_EDIT', 0b10); // 2
define('PERMISSIONS_PAGE_DELETE', 0b100); // 4
define('PERMISSIONS_PAGE_NEW', 0b1000); // 8
define('PERMISSIONS_CONTENT_EDIT', 0b10000); // 16
define('PERMISSIONS_ALL', 0b11111); // 31

$bitSet = new \TYPO3\CMS\Core\DataStructure\BitSet(PERMISSIONS_PAGE_SHOW | PERMISSIONS_PAGE_NEW);
$bitSet->get(PERMISSIONS_PAGE_SHOW); // true
$bitSet->get(PERMISSIONS_CONTENT_EDIT); // false

Another example shows how to possibly extend the :php:`\TYPO3\CMS\Core\DataStructure\BitSet` class.

::

<?php
declare(strict_types = 1);

class Permissions extends \TYPO3\CMS\Core\DataStructure\BitSet
{
public const NONE = 0b0; // 0
public const PAGE_SHOW = 0b1; // 1
public const PAGE_EDIT = 0b10; // 2
public const PAGE_DELETE = 0b100; // 4
public const PAGE_NEW = 0b1000; // 8
public const CONTENT_EDIT = 0b10000; // 16
public const ALL = 0b11111; // 31

/**
* @param int $permission
* @return bool
*/
public function hasPermission(int $permission): bool
{
return $this->get($permission);
}

/**
* @return bool
*/
public function hasAllPermissions(): bool
{
return $this->get(static::ALL);
}

/**
* @param int $permission
*/
public function allow(int $permission): void
{
$this->set($permission);
}
}

$permissions = new Permissions(Permissions::PAGE_SHOW | Permissions::PAGE_NEW);
$permissions->hasPermission(Permissions::PAGE_SHOW); // true
$permissions->hasPermission(Permissions::CONTENT_EDIT); // false


Impact
======

This class may come in handy in all situations where boolean flags need to be managed in an efficient way.

.. index:: PHP-API, ext:core
88 changes: 88 additions & 0 deletions typo3/sysext/core/Tests/Unit/DataStructure/BitSetTest.php
@@ -0,0 +1,88 @@
<?php
declare(strict_types = 1);

/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/

namespace TYPO3\CMS\Core\Tests\Unit\DataStructure;

use TYPO3\CMS\Core\DataStructure\BitSet;
use TYPO3\TestingFramework\Core\Unit\UnitTestCase;

/**
* Class TYPO3\CMS\Core\Tests\Unit\DataStructure\BitSetTest
*/
class BitSetTest extends UnitTestCase
{
/**
* @test
*/
public function defaultBitSetOnlyHasZeroByteSet(): void
{
$bitSet = new BitSet();
static::assertTrue($bitSet->get(0b0));
static::assertFalse($bitSet->get(0b1));
}

/**
* @test
*/
public function constructorSetsInternalSet(): void
{
$bitSet = new BitSet(0b1 | 0b100);
static::assertTrue($bitSet->get(0b1));
static::assertTrue($bitSet->get(0b100));
static::assertFalse($bitSet->get(0b10));
}

/**
* @test
*/
public function setSetsBit(): void
{
$bitSet = new BitSet(0b101);
static::assertTrue($bitSet->get(0b1));
static::assertTrue($bitSet->get(0b100));
static::assertFalse($bitSet->get(0b10));

$bitSet->set(0b10);
static::assertTrue($bitSet->get(0b10));
}

/**
* @test
*/
public function setValueSetsBit(): void
{
$bitSet = new BitSet();
static::assertFalse($bitSet->get(0b1));

$bitSet->setValue(0b1, true);
static::assertTrue($bitSet->get(0b1));

$bitSet->setValue(0b1, false);
static::assertFalse($bitSet->get(0b1));
}

/**
* @test
*/
public function clearUnsetsBit(): void
{
$bitSet = new BitSet(0b111);
$bitSet->unset(0b10);
static::assertTrue($bitSet->get(0b1));
static::assertTrue($bitSet->get(0b100));
static::assertFalse($bitSet->get(0b10));
}
}

0 comments on commit 81ddfe4

Please sign in to comment.