SSブログ

Data::Uniqidのsuniqidって変ですよね

cpanあたりにあったData::Uniqidというモジュールの話。大雑把にいえば、ユニークなIDをBase62で生成してくれるものなのですが、その中に、賞味期限が1日程度のユニークIDを生成してくれるsuniqidというものがあります。このsuniqidなんですが、ときどき長さゼロの文字列を返してくださるので、中身をみてみると、こんな感じでした。

sub suniqid { ########################################### get unique id #####
  my($s,$us)=gettimeofday();
  my($v)=sprintf("%06d%5d%06d",$us,substr($s,-5),$$);
  return(&base62($v));
}


gettimeofday()は、use Time::HiRes qw( gettimeofday usleep );してますので、エポックからの秒数とそのときのマイクロ秒を配列で返すものになります。$vは、見てのとおり、6桁のマイクロ秒とエポックからの秒数の下5桁を取ったものとプロセスIDを繋いだものです。マイクロ秒部分とプロセスID部分は6桁に満たない場合0がパディングされます。

ここで妙なのが、エポックからの秒数の下5桁をとっているsubstr($s,-5)なのですが、1日が86400秒なので、それなりに5桁以下になることってありますよね。しかも、この部分は%5dなので、substr($s,-5)が5桁未満の場合、$vはスペースで隙間の空いた数字列になるわけです。で、これがbase62()に渡されるわけなんですが、それがこれです。

sub base62() { ################################################### Base62 #####
  my($s)=@_;
  my(@c)=('0'..'9','a'..'z','A'..'Z');
  my(@p,$u,$v,$i,$n);
  my($m)=20;
  $p[0]=1;
  for $i (1..$m) {
    $p[$i]=Math::BigInt->new($p[$i-1]);
    $p[$i]=$p[$i]->bmul(62);
  }

  $v=Math::BigInt->new($s);
  for ($i=$m;$i>=0;$i--) {
    $v=Math::BigInt->new($v);
    ($n,$v)=$v->bdiv($p[$i]);
    $u.=$c[$n];
  }
  $u=~s/^0+//;

  return($u);
}


こんなのにスペースで隙間のある数字列渡したら、($n,$v)=$v->bdiv($p[$i]);の$n,$vが共にNaNになって、$uに連結される文字は0にしかならない。結局、$u=~s/^0+//;なんてしたら、そんな場合、長さ0の文字列にしかならないし。

なんで、こんな仕様なんでしょうね。
nice!(0)  コメント(1)  トラックバック(0) 
共通テーマ:日記・雑感

nice! 0

コメント 1

*生保単独*

個人的には、%5dが%05dの間違いか、Mike Wesemannのワナかのどちらかではないかと思ってるだけなんですが…。
by *生保単独* (2008-10-19 03:48) 

コメントを書く

お名前:[必須]
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

トラックバック 0

そんな手が確かに ブログトップ

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。