mruby parse.y scan_hexを読んでみよう
static int32_t
scan_hex(const int *start, int len, int *retlen)
scan_hex名前の通り十六進数の数字を渡したらintを返してくるのでしょう。
まずローカル変数を準備します。
static const char hexdigit[] = "0123456789abcdef0123456789ABCDEF";
const int *s = start;
int32_t retval = 0;
char *tmp;
hexdigitは大文字小文字の両方に対応しています。
下で出てくる ”&15”をすることで両方同じ結果になります。
while (len-- && *s && (tmp = (char*)strchr(hexdigit, *s))) {
retval <<= 4;
retval |= (tmp - hexdigit) & 15;
s++;
}
ここがこの関数の肝の部分ですね。
whileは
- lenが0になるまで
- sの文字列がnullになるまで
- hexdigitの中にsの文字が見つからなくなるまで
回ります。
strchrは見つかった文字のポインタを返します。そこからhexdigitの頭のアドレスを
引くとその文字のインデックスの数字がわかります。
その時15(0b1111)でandすることで16から0に戻ります。
16(0b10000) & 15(0b1111) = 0
17(0b10001) & 15(0b1111) = 1(0b0001)
...
これでfもFも同じインデックス15になります。
その見つかった15までの数をretvalにorで入れて4つ左にずらします。
これでffは最初のfが
1111になりこれを4つ左にずらし次のf 1111をまたいれます。
それが11111111となりこれは255なので見事にffがintになりました。