Подтвердить что ты не робот

Как реализовать битовую маску в php?

Я не уверен, что битмаска - правильный термин. Позвольте мне объяснить:

В php функция error_reporting может быть вызвана несколькими способами:

// 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);

Я получил термин битмаск с страницы php.net здесь

Во всяком случае, это то, что я реализовал метод SIMPLE под названием ls, который возвращает содержимое каталога.

Эта функция принимает 3 аргумента... ($ include_hidden = false, $return_absolute = false, $ext = false)

Поэтому, когда я вызываю функцию, я устанавливаю, как мне нужны результаты. Я хочу, чтобы результаты возвращали скрытые каталоги, хочу ли я только базовые имена и т.д.

поэтому, когда я вызываю функцию, которую я пишу

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

Я думал, что это будет гораздо более читаемым, если бы я мог просто указать, как я хочу вернуть данные?

так что-то вроде:

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

и т.д...

Как мне реализовать это с точки зрения тестирования, какие флаги были вызваны?

4b9b3361

Ответ 1

Это довольно просто. Сначала немного кода, чтобы продемонстрировать, как он может быть реализован. Если вы ничего не понимаете о том, что делает этот код или как он работает, не стесняйтесь задавать дополнительные вопросы в комментариях:

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);

Демо


Поскольку флаги являются целыми числами, на 32-битной платформе вы определяете до 32 флагов. На 64-битной платформе 64. Также возможно определить флаги в виде строк, и в этом случае количество доступных флагов будет более или менее бесконечным (в пределах системных ресурсов, конечно). Здесь, как это работает в двоичном формате (для простоты сокращается до 8-битных целых чисел).

FLAG_1
Dec:    1
Binary: 00000001

FLAG_2
Dec:    2
Binary: 00000010

FLAG_3
Dec:    4
Binary: 00000100

// And so on...

Когда вы объединяете флаги, чтобы передать их функции, вы ИЛИ их вместе. Давайте посмотрим, что произойдет, когда мы пройдем FLAG_1 | FLAG_3

  00000001
| 00000100
= 00000101

И когда вы хотите увидеть, какие флаги были установлены, вы и битмаска с флагом. Итак, давайте рассмотрим результат выше и посмотрим, установлен ли FLAG_3:

  00000101
& 00000100
= 00000100

... мы получаем значение флага назад, ненулевое целое число, но если мы видим, было ли установлено FLAG_2:

  00000101
& 00000010
= 00000000

... получаем нуль. Это означает, что вы можете просто оценить результат операции AND как логическое значение при проверке того, было ли передано значение.

Ответ 2

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..

Затем вы можете проверить отдельные флаги в своей функции ls:

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

Ответ 3

Другие предложили хорошие предложения, но в наши дни гораздо чаще встречаются в ассоциативных массивах вместо битмаски. Он гораздо читабельнее и позволяет передавать другие переменные, кроме только истинных/ложных значений. Что-то вроде этого:

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

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

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