Как реализовать битовую маску в 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 страница здесь
в любом случае суть в том, что я реализовал простой метод под названием 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 );
etc...
как бы я реализовал это с точки зрения тестирования, какие флаги имеют был вызван?
3 ответа:
это довольно просто на самом деле. Сначала немного кода, чтобы продемонстрировать, как это может быть реализовано. Если вы ничего не понимаете о том, что этот код делает или как он работает, не стесняйтесь задавать дополнительные вопросы в комментариях:
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 как логическое значение при проверке, было ли передано значение.
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 }
другие предложили хорошие предложения, но в эти дни это гораздо чаще, чтобы пройти в ассоциативные массивы вместо битовых масок. Это гораздо более читабельно и позволяет передавать другие переменные, отличные от истинных/ложных значений. Что-то вроде этого:
myFunction(['includeHidden' => true, 'fileExts' => false, 'string' => 'Xyz']); function myFunction($options) { // Set the default options $options += [ 'includeHidden' => false, 'fileExts' => true, 'string' => 'Abc', ]; if ($options['includeHidden']) { ... } ... }