前回 の記事の中で ACL のオプションを取得する QueryAccessPrivileges メソッドを紹介しました。このメソッドの戻り値は、以下の値の組み合わせだと紹介しました。例えば、文書の作成ができて、削除のできる場合には、1 + 2 の 3 となります。これにパブリック文書の読者権限も持っていると 67 となります。
上記のように、戻り値で組み合わされた値が返ってきたとき、あなたならどのように判定しますか?
値 | 定数 |
1 | DBACL_CREATE_DOCUMENTS |
2 | DBACL_DELETE_DOCUMENTS |
4 | DBACL_CREATE_PRIV_AGENTS |
8 | DBACL_CREATE_PRIV_FOLDERS_VIEWS |
16 | DBACL_CREATE_SHARED_FOLDERS_VIEWS |
32 | DBACL_CREATE_SCRIPT_AGENTS |
64 | DBACL_READ_PUBLIC_DOCUMENTS |
128 | DBACL_WRITE_PUBLIC_DOCUMENTS |
256 | DBACL_REPLICATE_COPY_DOCUMENTS |
オプションの値の意味
話を単純化するために上から 4 つの場合を考えます。オプションの値は 1、2、4、8 で、取りうる値(組み合わせ)は 0 から 15 となります。列にオプションの値、行に取りうる値を整理すると次のようになります。
1 | 2 | 4 | 8 | |
0 | × | × | × | × |
1 | 〇 | × | × | × |
2 | × | 〇 | × | × |
3 | 〇 | 〇 | × | × |
4 | × | × | 〇 | × |
5 | 〇 | × | 〇 | × |
6 | × | 〇 | 〇 | × |
7 | 〇 | 〇 | 〇 | × |
8 | × | × | × | 〇 |
9 | 〇 | × | × | 〇 |
10 | × | 〇 | × | 〇 |
11 | 〇 | 〇 | × | 〇 |
12 | × | × | 〇 | 〇 |
13 | 〇 | × | 〇 | 〇 |
14 | × | 〇 | 〇 | 〇 |
15 | 〇 | 〇 | 〇 | 〇 |
これですぐわかりますね。オプションの値は 2 進数の各ビットの値を表すということになります。
判定方法
では、13 を例にどのビットが立っているのか考えてみます。大きいビットから考えて、
- 8 で割って 1 以上(〇)
- 8 で割った余り 5 を 4 で割って 1 以上(〇)
- 4 で割った余り 1 を 2 で割って 1 未満(×)
- 2 で割った余りが 1(〇)
というよな判定となります。
これを逐一 If 文で書くと結構な分量になります。また、QueryAccessPrivileges のように 256( = 9 ビット)までとなるととんでもない分量になることが想像できます。
そこで、プログラミングらしく、ループを使って効率的に判定する方法を考えてみましょう。
Sub Initialize Dim iBit As Integer Dim iSrc As Integer 'サンプル地 Dim iOpt As Integer 'オプションの値 iSrc = 13 '上のビットから順に処理 For iBit = 3 To 0 Step -1 'ビットの値を算出 iOpt = 2 ^ iBit 'ビットが立っているか判定 If iSrc / iOpt >= 1 Then MsgBox CStr(iOpt) & " = 〇" Else MsgBox CStr(iOpt) & " = ×" End If 'ビットの値の余りを算出 iSrc = iSrc Mod iOpt Next End Sub |
べき乗の演算子(^)と剰余を求める命令(mod)を使い、上のビットから演算を進めることで、ループを効率的に活用しています。
なお、If 文の判定では、判定方法に記載した通り割り算を使用しましたが、以下のように書き換えることができます。
If iSrc >= iOpt Then |
割り算した結果を比較して判定するより、整数値を比較するだけの方が明らかに演算コストが安いですよね。
論理演算の動作
もっと簡単に判別する方法はないでしょうか? 実はあるんです。
それは、論理演算子 And を使用する方法です。If 文で複数の条件を記述する際に利用するあの And のことです。
If a = b And b = c Then |
And 演算子は上記のような使い方のほかに 2 つの値のビットを比較し、その結果を返す機能があります(上記判定もその一部)。事例に挙げた 13 の場合と 3 の And の結果は次のようになります。
13 And 8 = 1101 And 1000 = 1000 = 8 3 And 8 = 0011 And 1000 = 0000 = 0 |
And 一つあればそのビットが立っているか判定できることがわかります。
論理演算の活用
最初の表の定数は 1, 2, 4, 8, 16 … と各ビットの値が定数化されています。この定数と And とを活用すると保持しているオプションが ”ワンパン” で判定できます。
例えば『個人フォルダ/ビューの作成』を持っているか判定する場合、次のように記述します(iOpt に QueryAccessPrivileges の戻り値が入っている前提)。
If (iOpt And DBACL_CREATE_PRIV_FOLDERS_VIEWS) > 0 Then |
まとめ
今回は、QueryAccessPrivileges の戻り値を題材に論理演算子の活用方法についてまとめました。
ご存じの通り、コンピュータは 2 進数で動作しています。それを活用した演算子や言語仕様が各所にちりばめられています。10 進数で姓つしている私たちには気が付きにくいのですが、うまく活用することで、超お得になることがあります。
デザイナーヘルプやサンプルを見て、2 進数っぽいものが出てきたら調べてみましょう。お宝が発見できるかもしれませんよ。
0 件のコメント:
コメントを投稿