如何在 php 中实现位掩码


How to implement a bitmask in php?

我不确定bitmask是否是正确的术语。让我解释一下:

在 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 的 SIMPLE 方法,该方法返回目录的内容。

此函数需要 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 );

等。。。

在测试调用了哪些标志方面,我将如何实现这一点?

其实很简单。首先是一些代码来演示如何实现它。如果您对这段代码的作用或工作原理一无所知,请随时在评论中提出其他问题:

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']) {
        ...
    }
    ...
}

我有一个正在使用的 API - 文档非常薄。它给了我们一个整数,并说:

"信息在这些值中编码为位字段。位字段的工作原理是在同一整数中存储多个真/假值,而不是为每个值存储多个整数。要在位字段中查找值,您需要使用位掩码。

Bit     Decimal Value    Setting
0       1                Display
1       2                Sell
2       4                Kiosk Display
3       8                No Passes
4       16               Dolby Digital
5       32               THX
6       64               DLP
[etc]

我根据这里的其他答案想出了如何解决它,尽管我会分享我想出的功能。

我最终编写了这个函数:

<?php
function bitmap_decode( $label_array, $value, $return_item ) {
    $label_array = array_flip( $label_array ); // swap the keys and values
    $i = $label_array[ $return_item ]; // get the decimal key value for the item on the list
    $i =  2**$i; // use 2 to the nth power to get the decimal bitmap value for the item
    return $value & $i ? 1 : 0; // use the & operator to determine if the value is true or false. return 1 or 0 accordingly
}

。这将解析出值

$info1 = array(
    'Display',
    'Sell',
    'Kiosk Display',
    'No Passes',
    'Dolby Digital',
    'THX',
    'DLP',
);

$api_value = 5;
echo bitmap_decode( $info1, $api_value, 'Sell' ); // 0
$api_value = 35;
echo bitmap_decode( $info1, $api_value, 'Sell' ); // 1

然后我们可以做相反的事情 - 对值进行编码,而不必考虑任何非二进制数或类似的东西:

function bitmap_encode( $items, $label_array ) {
    $return = 0;
    $label_array = array_flip( $label_array ); // swap the keys and values
    foreach ( $items as $item ) {
        $i = $label_array[ $item ]; // get the decimal key value for the item on the list
        $i = 2**$i; // use 2 to the nth power to get the decimal bitmap value for the item
        $return += $i; // add $i to the return value
    }
    return $return;
}
// set these flags as true
$flags = array( 'Display', 'Sell', 'THX' );
echo bitmap_encode( $flags, $info1 ); // 35

我知道这并不能准确回答 OP 问题,但这是在 PHP 中制作位掩码系统的另一种方法。