web-dev-qa-db-fra.com

Comment implémenter un bitmask en php?

Je ne sais pas si bitmask est le terme correct. Laissez-moi expliquer:

En php, le error_reporting la fonction peut être appelée de plusieurs façons:

// Report simple running errors
error_reporting(E_ERROR | E_WARNING | E_PARSE);

// Reporting E_NOTICE can be good too (to report uninitialized
// variables or catch variable name misspellings ...)
error_reporting(E_ERROR | E_WARNING | E_PARSE | E_NOTICE);

// Report all errors except E_NOTICE
// This is the default value set in php.ini
error_reporting(E_ALL ^ E_NOTICE);

J'ai obtenu le terme bitmask sur la page php.net ici

Quoi qu'il en soit, j'ai implémenté une méthode SIMPLE appelée ls qui retourne le contenu d'un répertoire.

Cette fonction prend 3 arguments ... ($ include_hidden = false, $ return_absolute = false, $ ext = false)

Donc, quand j'appelle la fonction, je définis comment je veux les résultats. Si je veux que les résultats retournent des répertoires cachés, si je veux seulement les noms de base, etc.

donc quand j'appelle la fonction j'écris

ls(true, false, true)
ls(false, false, true)
ls(true, true, true)
etc...

Je pensais que ce serait beaucoup plus lisible si je pouvais simplement indiquer comment je veux que les données soient retournées?

donc quelque chose comme:

ls( INCLUDE_HIDDEN | HIDE_EXTS );
ls( SHOW_ABSOLUTE_PATHS | HIDE_EXTS );

etc...

Comment pourrais-je implémenter cela en termes de test des drapeaux qui ont été appelés?

69
AlexMorley-Finch

C'est assez simple en fait. D'abord un peu de code pour montrer comment l'implémenter. Si vous ne comprenez rien à ce que fait ce code ou comment il fonctionne, n'hésitez pas à poser des questions supplémentaires dans les commentaires:

const FLAG_1 = 0b0001; // 1
const FLAG_2 = 0b0010; // 2
const FLAG_3 = 0b0100; // 4
const FLAG_4 = 0b1000; // 8
// Can you see the pattern? ;-)

function show_flags ($flags) {
  if ($flags & FLAG_1) {
    echo "You passed flag 1!<br>\n";
  }
  if ($flags & FLAG_2) {
    echo "You passed flag 2!<br>\n";
  }
  if ($flags & FLAG_3) {
    echo "You passed flag 3!<br>\n";
  }
  if ($flags & FLAG_4) {
    echo "You passed flag 4!<br>\n";
  }
}

show_flags(FLAG_1 | FLAG_3);

Démo


Étant donné que les indicateurs sont des nombres entiers, sur une plate-forme 32 bits, vous définissez jusqu'à 32 indicateurs. Sur une plate-forme 64 bits, c'est 64. Il est également possible de définir les drapeaux comme des chaînes, auquel cas le nombre de drapeaux disponibles est plus ou moins infini (dans les limites des ressources système, bien sûr). Voici comment cela fonctionne en binaire (réduit à des entiers 8 bits pour plus de simplicité).

FLAG_1
Dec:    1
Binary: 00000001

FLAG_2
Dec:    2
Binary: 00000010

FLAG_3
Dec:    4
Binary: 00000100

// And so on...

Lorsque vous combinez les drapeaux pour les transmettre à la fonction, vous OR les réunissez. Voyons ce qui se passe lorsque nous transmettons FLAG_1 | FLAG_3

  00000001
| 00000100
= 00000101

Et lorsque vous voulez voir quels drapeaux ont été définis, vous ET le bitmask avec le drapeau. Donc, prenons le résultat ci-dessus et voyons si FLAG_3 a été mis en:

  00000101
& 00000100
= 00000100

... nous récupérons la valeur de l'indicateur, un entier non nul - mais si nous voyons si FLAG_2 a été mis en:

  00000101
& 00000010
= 00000000

... nous obtenons zéro. Cela signifie que vous pouvez simplement évaluer le résultat de l'opération ET en tant que booléen lorsque vous vérifiez si la valeur a été transmise.

140
DaveRandom
define( "INCLUDE_HIDDEN", 0x1 );
define( "HIDE_EXTS", 0x2 );
define( "SHOW_ABSOLUTE_PATHS", 0x4 );
//And so on, 0x8, 0x10, 0x20, 0x40, 0x80, 0x100, 0x200, 0x400, 0x800 etc..

Vous pouvez ensuite vérifier les indicateurs individuels dans votre fonction ls:

if( $flags & INCLUDE_HIDDEN ) { //<-- note just a single &, bitwise and
    //$flags have INCLUDE_HIDDEN
}
17
Esailija

Les autres ont proposé de bonnes suggestions, mais ces jours-ci, il est beaucoup plus courant de passer tableaux associatifs au lieu de masques de bits. Il est beaucoup plus lisible et vous permet de passer dans d'autres variables autres que des valeurs vraies/fausses. Quelque chose comme ça:

myFunction(['includeHidden' => true, 'fileExts' => false, 'string' => 'Xyz']);

function myFunction($options) {
    // Set the default options
    $options += [
        'includeHidden' => false,
        'fileExts' => true,
        'string' => 'Abc',
    ];

    if ($options['includeHidden']) {
        ...
    }
    ...
}
3
Simon East