Bivio::Biz::Random
# Copyright (c) 2006-2007 bivio Software, Inc. All Rights Reserved. # $Id$ package Bivio::Biz::Random; use strict; use Bivio::Base 'Bivio::UNIVERSAL'; use Bivio::MIME::Base64; use IO::File (); my($_DEV) = -r '/dev/urandom' ? '/dev/urandom' : -r '/dev/random' ? '/dev/random' : undef; sub bytes { my($proto, $length) = @_; $length = b_use('Type.Integer')->from_literal_or_die($length); my($f, $res); return $_DEV ? ($f = IO::File->new("< $_DEV")) && defined($f->sysread($res, $length)) && defined($f->close) ? $res : $proto->die("$_DEV: $!") : substr( pack('L', int(rand(0xffffffff))) x int(($length + 3)/4), 0, $length, ); } sub hex_digits { my($proto, $length) = @_; $length = b_use('Type.Integer')->from_literal_or_die($length); return substr( unpack('h*', shift->bytes(int(($length + 1) / 2))), 0, $length, ); } sub integer { my($proto, $ceiling, $floor) = @_; if (defined($ceiling)) { b_die($ceiling, ': ceiling must be positive') unless $ceiling > 0; } else { $ceiling = $proto->use('Type.Integer')->get_max; } if (defined($floor)) { b_die($floor, ': floor must be non-negative') unless $floor >= 0; } else { $floor = 0; } b_die($floor, ': floor must be less than ceiling: ', $ceiling) unless $ceiling > $floor; return unpack('L', $proto->bytes(4)) % ($ceiling - $floor) + $floor; } sub password { return Bivio::MIME::Base64->http_encode(shift->bytes(12)); } sub string { my($proto, $length, $chars) = @_; $length ||= 8; $chars ||= [0..9, 'a' .. 'z']; return join('', map( $chars->[ord($_) % @$chars], split(//, $proto->bytes($length)), )); } 1;