87 votes

Comment implémenter un bitmask en php ?

Je ne suis pas sûr que bitmask soit le terme correct. Laissez-moi vous expliquer :

En php, le error_reporting 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 trouvé le terme bitmask sur la page de php.net. ici

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

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

Ainsi, lorsque j'appelle la fonction, je définis comment je veux obtenir les résultats. Si je veux que les résultats renvoient les 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 renvoyées ?

donc quelque chose comme :

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

etc...

Comment puis-je mettre en œuvre cette méthode pour tester les drapeaux qui ont été appelés ?

161voto

DaveRandom Points 45661

C'est assez simple en fait. Tout d'abord, un peu de code pour démontrer comment il peut être mis en œuvre. 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


Comme les drapeaux sont des entiers, sur une plate-forme 32 bits, vous pouvez définir jusqu'à 32 drapeaux. Sur une plateforme 64 bits, c'est 64. Il est également possible de définir les drapeaux comme des chaînes de caractères, auquel cas le nombre de drapeaux disponibles est plus ou moins infini (dans les limites des ressources du système, bien sûr). Voici comment cela fonctionne en binaire (réduit à des entiers de 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 passer à la fonction, vous les OR ensemble. Regardons ce qui se passe lorsque nous passons FLAG_1 | FLAG_3

  00000001
| 00000100
= 00000101

Et quand on veut voir quels drapeaux ont été activés, on fait ET le bitmask avec le drapeau. Donc, prenons le résultat ci-dessus et voyons si FLAG_3 a été fixé :

  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é fixé :

  00000101
& 00000010
= 00000000

...on obtient zéro. Cela signifie que vous pouvez simplement évaluer le résultat de l'opération AND comme un booléen lorsque vous vérifiez si la valeur a été transmise.

17voto

Esailija Points 74052
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 drapeaux individuels dans votre ls fonction :

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

2voto

Simon Points 4467

Les autres ont fait de bonnes suggestions, mais de nos jours, il est beaucoup plus courant de passer dans tableaux associatifs au lieu de bitmasks. C'est beaucoup plus lisible et permet de passer d'autres variables que les simples valeurs vrai/faux. 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']) {
        ...
    }
    ...
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X