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は

  1. lenが0になるまで
  2. sの文字列がnullになるまで
  3. 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になりました。