1############################################################################# 2# Math/String/Charset/Grouped.pm -- a charset of charsets for Math/String 3# 4# Copyright (C) 1999-2003 by Tels. All rights reserved. 5############################################################################# 6 7package Math::String::Charset::Grouped; 8 9require 5.005; # requires this Perl version or later 10use strict; 11 12use base 'Math::String::Charset'; 13 14our $VERSION; 15$VERSION = '1.30'; # Current version of this package 16 17use Math::BigInt; 18 19our $die_on_error; 20$die_on_error = 1; # set to 0 to not die 21 22# following hash values are used: 23# _clen : length of one character (all chars must have same len unless sep) 24# _ones : list of one-character strings (cross of _end and _start) 25# _start : contains array of all valid start characters 26# _end : contains hash (for easier lookup) of all valid end characters 27# _order : = 1 28# _type : = 1 29# _error : error message or "" 30# _count : array of count of different strings with length x 31# _sum : array of starting number for strings with length x 32# _sum[x] = _sum[x-1]+_count[x-1] 33# _cnt : number of elements in _count and _sum (as well as in _scnt & _ssum) 34# _cnum : number of characters in _ones as BigInt (for speed) 35# _minlen: minimum string length (anything shorter is invalid), default -inf 36# _maxlen: maximum string length (anything longer is invalid), default +inf 37# _scale : optional input/output scale 38 39# simple ones: 40# _sep : separator string (undef for none) 41# _map : mapping character to number 42 43# higher orders: 44# _bi : hash with refs to array of bi-grams 45# _bmap : hash with refs to hash of bi-grams 46# _scnt : array of hashes, count of strings starting with this character 47 48# grouped: 49# _spat : array with pattern of charsets 8for each stirnglen one ARRAY ref) 50 51############################################################################# 52# private, initialize self 53 54sub _strict_check 55 { 56 # a per class check, to be overwritten by subclasses 57 my $self = shift; 58 my $value = shift; 59 60 my $class = ref($self); 61 return $self->{_error} = "Wrong type '$self->{_type}' for $class" 62 if $self->{_type} != 1; 63 return $self->{_error} = "Wrong order'$self->{_order}' for $class" 64 if $self->{_order} != 1; 65 foreach my $key (keys %$value) 66 { 67 return $self->{_error} = "Illegal parameter '$key' for $class" 68 if $key !~ /^(start|minlen|maxlen|sep|sets|end|charlen|scale)$/; 69 } 70 } 71 72sub _initialize 73 { 74 # set yourself to the value represented by the given string 75 my $self = shift; 76 my $value = shift; 77 78 $self->{_clen} = $value->{charlen}; 79 $self->{_sep} = $value->{sep}; # separator char 80 81 return $self->{_error} = "Need HASH ref as 'sets'" 82 if (ref($value->{sets}) ne 'HASH'); 83 84 # make copy at same time 85 foreach my $key (keys %{$value->{sets}}) 86 { 87 $self->{_sets}->{$key} = $value->{sets}->{$key}; 88 } 89 90 # start/end are sets 1 and -1, respectively, and overwrite 'sets' 91 $self->{_sets}->{1} = $value->{start} if exists $value->{start}; 92 $self->{_sets}->{-1} = $value->{end} if exists $value->{end}; 93 $self->{_sets}->{0} = $value->{chars} if exists $value->{chars}; 94 # default set 95 $self->{_sets}->{0} = ['a'..'z'] if !defined $self->{_sets}->{0}; 96 97 my $sets = $self->{_sets}; # shortcut 98 foreach my $set (keys %$sets) 99 { 100 return $self->{_error} = 101 "Entries in 'sets' must be ref to Math::String::Charset or ARRAY" 102 if ((ref($sets->{$set}) ne 'ARRAY') && 103 (ref($sets->{$set}) ne 'Math::String::Charset')); 104 105 # so for each set, make a Math::String::Charset 106 $sets->{$set} = Math::String::Charset->new($sets->{$set}) 107 if ref($sets->{$set}) eq 'ARRAY'; 108 } 109 $self->{_start} = $sets->{1} || $sets->{0}; 110 $self->{_end} = $sets->{-1} || $sets->{0}; 111 112 $self->{_clen} = $self->{_start}->charlen() if 113 ((!defined $self->{_clen}) && (!defined $self->{_sep})); 114 115 # build _ones list (cross from start/end) 116 $self->{_ones} = []; 117 118 # _end is a simple charset, so use it's map directly 119 my $end = $self->{_end}->{_map}; 120 my $o = $self->{_ones}; 121 foreach ($self->{_start}->start()) 122 { 123 push @$o, $_ if exists $end->{$_}; 124 } 125 #print "\n"; 126 127 # some tests for validity 128 if (!defined $self->{_sep}) 129 { 130 foreach (keys %{$self->{_sets}}) 131 { 132 my $l = $self->{_sets}->{$_}->charlen(); 133 return $self->{_error} = 134 "Illegal character length '$l' for charset '$_', expected '$self->{_clen}'" 135 if $self->{_sets}->{$_}->charlen() != $self->{_clen}; 136 137 } 138 } 139 $self->{_cnum} = Math::BigInt->new( scalar @{$self->{_ones}} ); 140 # initialize array of counts for len of 0..1 141 $self->{_cnt} = 2; # cached amount of class-sizes 142 if ($self->{_minlen} <= 0) 143 { 144 $self->{_count}->[0] = 1; # '' is one string 145 my $sl = $self->{_start}->length(); 146 my $el = $self->{_end}->length(); 147 $self->{_count}->[1] = $self->{_cnum}; 148 $self->{_count}->[2] = $sl * $el; 149 # init _sum array 150 $self->{_sum}->[0] = Math::BigInt->bzero(); 151 $self->{_sum}->[1] = Math::BigInt->bone(); # '' is 1 string 152 $self->{_sum}->[2] = $self->{_count}->[1] + $self->{_sum}->[1]; 153 $self->{_sum}->[3] = $self->{_count}->[2] + $self->{_sum}->[2]; 154 # init set patterns 155 $self->{_spat}->[1] = [ undef, $self->{_sets}->{0} ]; 156 $self->{_spat}->[2] = [ undef, $self->{_start}, $self->{_end} ]; 157 } 158 else 159 { 160 $self->{_cnt} = 0; # cached amount of class-sizes 161 } 162 163 # from _ones, make mapping name => number 164 my $i = Math::BigInt->bone(); 165 foreach (@{$self->{_ones}}) 166 { 167 $self->{_map}->{$_} = $i++; 168 } 169 170 if ($self->{_cnum}->is_zero()) 171 { 172 $self->{_minlen} = 2 if $self->{_minlen} == 1; # no one's 173 # check whether charset can have 2-character long strings 174 if ($self->{_count}->[2] == 0) 175 { 176 $self->{_minlen} = 3 if $self->{_minlen} == 2; # no two's 177 # check whether some path from start to end set exists, if not: empty 178 } 179 } 180 return $self->{_error} = 181 "Minlen ($self->{_minlen} must be smaller than maxlen ($self->{_maxlen})" 182 if ($self->{_minlen} > $self->{_maxlen}); 183 return $self; 184 } 185 186sub dump 187 { 188 my $self = shift; 189 190 my $txt = "type: GROUPED\n"; 191 192 foreach my $set (sort { $b<=>$a } keys %{$self->{_sets}}) 193 { 194 $txt .= " $set => ". $self->{_sets}->{$set}->dump(' '); 195 } 196 $txt .= "ones : " . join(' ',@{$self->{_ones}}) . "\n"; 197 $txt; 198 } 199 200sub _calc 201 { 202 # given count of len 1..x, calculate count for y (y > x) and all between 203 # x and y 204 # currently re-calcs from 2 on, we could save the state and only calculate 205 # the missing counts. 206 207# print "calc ",caller(),"\n"; 208 my $self = shift; 209 my $max = shift || 1; $max = 1 if $max < 1; 210 return if $max <= $self->{_cnt}; 211 212# print "in _calc $self $max\n"; 213 my $i = $self->{_cnt}; # last defined element 214 my $last = $self->{_count}->[$i]; 215 while ($i++ <= $max) 216 { 217 # build list of charsets for this length 218 my $spat = []; # set patterns 219 my $sets = $self->{_sets}; # shortcut 220 for (my $j = 1; $j <= $i; $j++) 221 { 222 my $r = $j-$i-1; # reverse 223# print "$j reversed $r (for $i)\n"; 224 $spat->[$j] = $sets->{$j} || $sets->{$r}; # one of both? 225 $spat->[$j] = $sets->{$j}->merge($sets->{$r}) if 226 exists $sets->{$j} && exists $sets->{$r}; # both? 227 $spat->[$j] = $sets->{0} unless defined $spat->[$j]; # none? 228# print $spat->[$j]->dump(),"\n"; 229 } 230 $self->{_spat}->[$i] = $spat; # store 231 # for each charset, take size and mul together 232 $last = Math::BigInt->bone(); 233 for (my $j = 1; $j <= $i; $j++) 234 { 235# print "$i $spat->[$j]\n"; 236 $last *= $spat->[$j]->length(); 237# print "last $last ",$spat->[$j]->length()," ($spat->[$j])\n"; 238 } 239 $self->{_count}->[$i] = $last; 240# print "$i: count $last "; 241 $self->{_sum}->[$i] = $self->{_sum}->[$i-1] + $self->{_count}->[$i-1]; 242# print "sum $self->{_sum}->[$i]\n"; 243 } 244 $self->{_cnt} = $i-1; # store new cache size 245 return; 246 } 247 248sub is_valid 249 { 250 # check wether a string conforms to the given charset sets 251 my $self = shift; 252 my $str = shift; 253 254 # print "$str\n"; 255 return 0 if !defined $str; 256 return 1 if $str eq '' && $self->{_minlen} <= 0; 257 258 my @chars; 259 if (defined $self->{_sep}) 260 { 261 @chars = split /$self->{_sep}/,$str; 262 shift @chars if $chars[0] eq ''; 263 pop @chars if $chars[-1] eq $self->{_sep}; 264 } 265 else 266 { 267 my $i = 0; my $len = CORE::length($str); my $clen = $self->{_clen}; 268 while ($i < $len) 269 { 270 push @chars, substr($str,$i,$clen); $i += $clen; 271 } 272 } 273 # length okay? 274 return 0 if scalar @chars < $self->{_minlen}; 275 return 0 if scalar @chars > $self->{_maxlen}; 276 277 # valid start char? 278 return 0 unless defined $self->{_start}->map($chars[0]); 279 return 1 if @chars == 1; 280 # further checks for strings longer than 1 281 my $k = 1; 282 my $d = scalar @chars; 283 $self->_calc($d) if ($self->{_cnt} < $d); 284 my $spat = $self->{_spat}->[$d]; 285 foreach my $c (@chars) 286 { 287 return 0 if !defined $spat->[$k++]->map($c); 288 } 289 # all tests passed 290 1; 291 } 292 293sub minlen 294 { 295 my $self = shift; 296 297 $self->{_minlen}; 298 } 299 300sub maxlen 301 { 302 my $self = shift; 303 304 $self->{_maxlen}; 305 } 306 307sub start 308 { 309 # this returns all the starting characters in a list, or in case of a simple 310 # charset, simple the charset 311 # in scalar context, returns length of starting set, for simple charsets this 312 # equals the length 313 my $self = shift; 314 315 wantarray ? @{$self->{_start}} : scalar @{$self->{_start}}; 316 } 317 318sub end 319 { 320 # this returns all the end characters in a list, or in case of a simple 321 # charset, simple the charset 322 # in scalar context, returns length of end set, for simple charsets this 323 # equals the length 324 my $self = shift; 325 326 wantarray ? sort keys %{$self->{_end}} : scalar keys %{$self->{_end}}; 327 } 328 329sub ones 330 { 331 # this returns all the one-char strings (in scalar context the count of them) 332 my $self = shift; 333 334 wantarray ? @{$self->{_ones}} : scalar @{$self->{_ones}}; 335 } 336 337sub num2str 338 { 339 # convert Math::BigInt/Math::String to string 340 # in list context, return (string,stringlen) 341 my $self = shift; 342 my $x = shift; 343 344 $x = new Math::BigInt($x) unless ref $x; 345 return undef if ($x->sign() !~ /^[+-]$/); 346 if ($x->is_zero()) 347 { 348 return wantarray ? ('',0) : ''; 349 } 350 my $j = $self->{_cnum}; # nr of chars 351 352 if ($x <= $j) 353 { 354 my $c = $self->{_ones}->[$x-1]; 355 return wantarray ? ($c,1) : $c; # string len == 1 356 } 357 358 my $digits = $self->chars($x); my $d = $digits; 359 # now treat the string as it were a zero-padded string of length $digits 360 361 my $es=""; # result 362 # copy input, make positive number, correct to $digits and cater for 0 363 my $y = Math::BigInt->new($x); $y->babs(); 364 #print "fac $j y: $y new: "; 365 $y -= $self->{_sum}->[$digits]; 366 367 $self->_calc($d) if ($self->{_cnt} < $d); 368 #print "y: $y\n"; 369 my $mod = 0; my $s = $self->{_sep}; $s = '' if !defined $s; 370 my $spat = $self->{_spat}->[$d]; # set pattern 371 my $k = $d; 372 while (!$y->is_zero()) 373 { 374 #print "bfore: y/fac: $y / $j \n"; 375 ($y,$mod) = $y->bdiv($spat->[$k]->length()); 376 #$es = $self->{_ones}->[$mod] . $s.$es; 377 $es = $spat->[$k--]->char($mod) . $s.$es; # find mod'th char 378 #print "after: div: $y rem: $mod \n"; 379 $digits --; # one digit done 380 } 381 # padd the remaining digits with the zero-symbol 382 while ($digits-- > 0) 383 { 384 $es = $spat->[$k--]->char(0) . $s . $es; 385 } 386 $es =~ s/$s$//; # strip last sep 'char' 387 wantarray ? ($es,$d) : $es; 388 } 389 390sub str2num 391 { 392 # convert Math::String to Math::BigInt 393 my $self = shift; 394 my $str = shift; # simple string 395 396 my $int = Math::BigInt->bzero(); 397 my $i = CORE::length($str); 398 399 return $int if $i == 0; 400 # print "str2num $i $clen '$str'\n"; 401 my $map = $self->{_map}; 402 my $clen = $self->{_clen}; # len of one char 403 404 if ((!defined $self->{_sep}) && ($i == $clen)) 405 { 406 return $int->bnan() if !exists $map->{$str}; 407 return $map->{$str}->copy(); 408 } 409 410 my $mul = Math::BigInt->bone(); 411 my $cs; # charset at pos i 412 my $k = 1; # position 413 my $c = 0; # chars in string 414 if (!defined $self->{_sep}) 415 { 416 return $int->bnan() if $i % $clen != 0; # not multiple times clen 417 $c = int($i/$clen); 418 $self->_calc($c) if ($self->{_cnt} < $c); 419 my $spat = $self->{_spat}->[$c]; 420# print "$c ($self->{_cnt}) spat: ",scalar @$spat,"\n"; 421 $i -= $clen; 422 $k = $c; 423 while ($i >= 0) 424 { 425 $cs = $spat->[$k--]; # charset at pos k 426# print "$i $k $cs nr $int "; 427# print "mapped ",substr($str,$i,$clen)," => ", 428# $cs->map(substr($str,$i,$clen)) || 0; 429# print " mul $mul => "; 430 $int += $mul * $cs->map(substr($str,$i,$clen)); 431 $mul *= $cs->length(); 432# print "mul $mul\n"; 433 $i -= $clen; 434 } 435 } 436 else 437 { 438 # with sep char 439 my @chars = split /$self->{_sep}/, $str; 440 shift @chars if $chars[0] eq ''; # strip leading sep 441 pop @chars if $chars[-1] eq $self->{_sep}; # strip trailing sep 442 $c = scalar @chars; 443 $self->_calc($c) if ($self->{_cnt} < $c); 444 my $spat = $self->{_spat}->[$c]; 445 $k = $c; 446 foreach (reverse @chars) 447 { 448 $cs = $spat->[$k--]; # charset at pos k 449 $int += $mul * $cs->map($_); 450 $mul *= $cs->length(); 451 } 452 } 453 $int + $self->{_sum}->[$c]; # add base sum 454 } 455 456#sub char 457# { 458# # return nth char from charset 459# my $self = shift; 460# my $char = shift || 0; 461# 462# return undef if $char > scalar @{$self->{_ones}}; # dont create spurios elems 463# return $self->{_ones}->[$char]; 464# } 465 466sub first 467 { 468 my $self = shift; 469 my $count = abs(shift || 0); 470 471 return if $count < $self->{_minlen}; 472 return if defined $self->{_maxlen} && $count > $self->{_maxlen}; 473 return '' if $count == 0; 474 475 return $self->{_ones}->[0] if $count == 1; 476 477 $self->_calc($count); 478 my $spat = $self->{_spat}->[$count]; 479 my $es = ''; 480 my $s = $self->{_sep} || ''; 481 for (my $i = 1; $i <= $count; $i++) 482 { 483 $es .= $s . $spat->[$i]->char(0); 484 } 485 $s = quotemeta($s); 486 $es =~ s/^$s// if $s ne ''; # remove first sep 487 $es; 488 } 489 490sub last 491 { 492 my $self = shift; 493 my $count = abs(shift || 0); 494 495 return if $count < $self->{_minlen}; 496 return if defined $self->{_maxlen} && $count > $self->{_maxlen}; 497 return '' if $count == 0; 498 499 return $self->{_ones}->[-1] if $count == 1; 500 501 $self->_calc($count); 502 my $spat = $self->{_spat}->[$count]; 503 my $es = ''; 504 my $s = $self->{_sep} || ''; 505 for (my $i = 1; $i <= $count; $i++) 506 { 507 $es .= $s . $spat->[$i]->char(-1); 508 } 509 $s = quotemeta($s); 510 $es =~ s/^$s// if $s ne ''; # remove first sep 511 $es; 512 } 513 514sub next 515 { 516 my $self = shift; 517 my $str = shift; 518 519 if ($str->{_cache} eq '') # 0 => 1 520 { 521 my $min = $self->{_minlen}; $min = 1 if $min <= 0; 522 $str->{_cache} = $self->first($min); 523 return; 524 } 525 526 # only the rightmost digit is adjusted. If this overflows, we simple 527 # invalidate the cache. The time saved by updating the cache would be to 528 # small to be of use, especially since updating the cache takes more time 529 # then. Also, if the cached isn't used later, we would have spent the 530 # update-time in vain. 531 532 # for higher orders not ready yet 533 $str->{_cache} = undef; 534 } 535 536sub prev 537 { 538 my $self = shift; 539 my $str = shift; 540 541 if ($str->{_cache} eq '') # 0 => -1 542 { 543 my $min = $self->{_minlen}; $min = -1 if $min >= 0; 544 $str->{_cache} = $self->first($min); 545 return; 546 } 547 548 # for higher orders not ready yet 549 $str->{_cache} = undef; 550 } 551 552__END__ 553 554############################################################################# 555 556=pod 557 558=head1 NAME 559 560Math::String::Charset::Grouped - A charset of simple charsets for Math::String objects. 561 562=head1 SYNOPSIS 563 564 use Math::String::Charset::Grouped; 565 566=head1 REQUIRES 567 568perl5.005, Exporter, Math::BigInt, Math::String::Charset 569 570=head1 EXPORTS 571 572Exports nothing. 573 574=head1 DESCRIPTION 575 576This module lets you create an charset object, which is used to construct 577Math::String objects. 578 579This object can assign for each position in a Math::String a different simple 580charset (aka a Math::String::Charset object of order => 1, type => 0). 581 582=over 1 583 584=item Default charset 585 586The default charset is the set containing "abcdefghijklmnopqrstuvwxyz" 587(thus producing always lower case output). 588 589=back 590 591=head1 ERORRS 592 593Upon error, the field C<_error> stores the error message, then die() is called 594with this message. If you do not want the program to die (f.i. to catch the 595errors), then use the following: 596 597 use Math::String::Charset::Grouped; 598 599 $Math::String::Charset::Grouped::die_on_error = 0; 600 601 $a = new Math::String::Charset::Grouped (); # error, empty set! 602 print $a->error(),"\n"; 603 604=head1 INTERNAL DETAILS 605 606This object caches certain calculation results (f.i. the number of possible 607combinations for a certain string length), thus greatly speeding up 608sequentiell Math::String conversations from string to number, and vice versa. 609 610=head1 METHODS 611 612=over 613 614=item new() 615 616 new(); 617 618Create a new Math::Charset::Grouped object. 619 620The constructor takes a HASH reference. The following keys can be used: 621 622 minlen Minimum string length, -inf if not defined 623 maxlen Maximum string length, +inf if not defined 624 sets hash, table with charsets for the different places 625 start array ref to list of all valid (starting) characters 626 end array ref to list of all valid ending characters 627 sep separator character, none if undef 628 629C<start> and C<end> are synomyms for C<< sets->{1} >> and C<< sets->{-1} >>, 630respectively. The will override what you specify in sets and are only for 631convienence. 632 633The resulting charset will always be of order 1, type 1. 634 635=over 2 636 637=item start 638 639C<start> contains an array reference to all valid starting 640characters, e.g. no valid string can start with a character not listed here. 641 642The same can be acomplished by specifying C<< sets->{1} >>. 643 644=item sets 645 646C<sets> contains a hash reference, each key of the hash indicates an index. 647Each of the hash entries B<MUST> point either to an ARRAY reference or a 648Math::String::Charset of order 1, type 0. 649 650Positive indices (greater than one) count from the left side, negative from 651the right. 0 denotes the default charset to be used for unspecified places. 652 653The index count will be used for all string length, so that C<< sets->{2} >> always 654refers to the second character from the left, no matter how many characters 655the string actually has. 656 657At each of the position indexed by a key, the appropriate charset will be used. 658 659Example for specifying that strings must start with upper case letters, 660followed by lower case letters and can end in either a lower case letter or a 661number: 662 663 sets => { 664 0 => ['a'..'z'], # the default 665 1 => ['A'..'Z'], # first character is always A..Z 666 -1 => ['a'..'z','0'..'9'], # last is q..z,0..9 667 } 668 669In case of overlapping, a cross between the two charsets will be used, that 670contains all characters from both of them. The default charset will only 671be used when none of the charsets counting from left or right matches. 672 673Given the definition above, valid strings with length 1 consist of: 674 675 ['A'..'Z','0'..'9'] 676 677Imagine having specified a set at position 2, too: 678 679 sets => { 680 0 => ['a'..'z'], # the default 681 1 => ['A'..'Z'], # first character is always A..Z 682 2 => ['-','+','2'], # second character is - or + 683 -1 => ['a'..'z','0'..'9'], # last is q..z,0..9 684 } 685 686For strings of length one, this character set will not be used. For strings 687with length 2 it will be crossed with the set at -1, so that the two-character 688long strings will start with ['A'..'Z'] and end in the characters 689['-','+','2','0','1','3'..'9']. 690 691The cross is build from left to right, that is first come all characters that 692are in the set counting from left, and then all characters in the set 693counting from right, except the ones that are in both (since no doubles must be 694used). 695 696=item end 697 698C<end> contains an array reference to all valid ending 699characters, e.g. no valid string can end with a character not listed here. 700Note that strings of length 1 start B<and> end with their only 701character, so the character must be listed in C<end> and C<start> to produce 702a string with one character. 703The same can be acomplished by specifying C<< sets->{-1} >>. 704 705=item minlen 706 707Optional minimum string length. Any string shorter than this will be invalid. 708Must be shorter than a (possible defined) maxlen. If not given is set to -inf. 709Note that the minlen might be adjusted to a greater number, if it is set to 1 710or greater, but there are not valid strings with 2,3 etc. In this case the 711minlen will be set to the first non-empty class of the charset. 712 713=item maxlen 714 715Optional maximum string length. Any string longer than this will be invalid. 716Must be longer than a (possible defined) minlen. If not given is set to +inf. 717 718=back 719 720=item minlen() 721 722 $charset->minlen(); 723 724Return minimum string length. 725 726=item maxlen() 727 728 $charset->maxlen(); 729 730Return maximum string length. 731 732=item length() 733 734 $charset->length(); 735 736Return the number of items in the charset, for higher order charsets the 737number of valid 1-character long strings. Shortcut for 738C<< $charset->class(1) >>. 739 740=item count() 741 742Returns the count of all possible strings described by the charset as a 743positive BigInt. Returns 'inf' if no maxlen is defined, because there should 744be no upper bound on how many strings are possible. 745 746If maxlen is defined, forces a calculation of all possible L</class()> values 747and may therefore be very slow on the first call, it also caches possible 748lot's of values if maxlen is very high. 749 750=item class() 751 752 $charset->class($order); 753 754Return the number of items in a class. 755 756 print $charset->class(5); # how many strings with length 5? 757 758=item char() 759 760 $charset->char($nr); 761 762Returns the character number $nr from the set, or undef. 763 764 print $charset->char(0); # first char 765 print $charset->char(1); # second char 766 print $charset->char(-1); # last one 767 768=item lowest() 769 770 $charset->lowest($length); 771 772Return the number of the first string of length $length. This is equivalent 773to (but much faster): 774 775 $str = $charset->first($length); 776 $number = $charset->str2num($str); 777 778=item highest() 779 780 $charset->highest($length); 781 782Return the number of the last string of length $length. This is equivalent 783to (but much faster): 784 785 $str = $charset->first($length+1); 786 $number = $charset->str2num($str); 787 $number--; 788 789=item order() 790 791 $order = $charset->order(); 792 793Return the order of the charset: is always 1 for grouped charsets. 794See also L</type()>. 795 796=item type() 797 798 $type = $charset->type(); 799 800Return the type of the charset: is always 1 for grouped charsets. 801See also L</order()>. 802 803=item charlen() 804 805 $character_length = $charset->charlen(); 806 807Return the length of one character in the set. 1 or greater. All charsets 808used in a grouped charset must have the same length, unless you specify a 809seperator char. 810 811=item seperator() 812 813 $sep = $charset->seperator(); 814 815Returns the separator string, or undefined if none is used. 816 817=item chars() 818 819 $chars = $charset->chars( $bigint ); 820 821Returns the number of characters that the string would have, when you would 822convert $bigint (Math::BigInt or Math::String object) back to a string. 823This is much faster than doing 824 825 $chars = length ("$math_string"); 826 827since it does not need to actually construct the string. 828 829=item first() 830 831 $charset->first( $length ); 832 833Return the first string with a length of $length, according to the charset. 834See C<lowest()> for the corrospending number. 835 836=item last() 837 838 $charset->last( $length ); 839 840Return the last string with a length of $length, according to the charset. 841See C<highest()> for the corrospending number. 842 843=item is_valid() 844 845 $charset->is_valid(); 846 847Check wether a string conforms to the charset set or not. 848 849=item error() 850 851 $charset->error(); 852 853Returns "" for no error or an error message that occured if construction of 854the charset failed. Set C<$Math::String::Charset::die_on_error> to C<0> to 855get the error message, otherwise the program will die. 856 857=item start() 858 859 $charset->start(); 860 861In list context, returns a list of all characters in the start set, that is 862the ones used at the first string position. 863In scalar context returns the lenght of the B<start> set. 864 865Think of the start set as the set of all characters that can start a string 866with one or more characters. The set for one character strings is called 867B<ones> and you can access if via C<< $charset->ones() >>. 868 869=item end() 870 871 $charset->end(); 872 873In list context, returns a list of all characters in the end set, aka all 874characters a string can end with. 875In scalar context returns the lenght of the B<end> set. 876 877=item ones() 878 879 $charset->ones(); 880 881In list context, returns a list of all strings consisting of one character. 882In scalar context returns the lenght of the B<ones> set. 883 884This list is the cross of B<start> and B<end>. 885 886Think of a string of only one character as if it starts with and ends in this 887character at the same time. 888 889The order of the chars in C<ones> is the same ordering as in C<start>. 890 891=item prev() 892 893 $string = Math::String->new( ); 894 $charset->prev($string); 895 896Give the charset and a string, calculates the previous string in the sequence. 897This is faster than decrementing the number of the string and converting the 898new number to a string. This routine is mainly used internally by Math::String 899and updates the cache of the given Math::String. 900 901=item next() 902 903 $string = Math::String->new( ); 904 $charset->next($string); 905 906Give the charset and a string, calculates the next string in the sequence. 907This is faster than incrementing the number of the string and converting the 908new number to a string. This routine is mainly used internally by Math::String 909and updates the cache of the given Math::String. 910 911=back 912 913=head1 EXAMPLES 914 915 use Math::String::Charset::Grouped; 916 917 # not ready yet 918 919=head1 BUGS 920 921None doscovered yet. 922 923=head1 AUTHOR 924 925If you use this module in one of your projects, then please email me. I want 926to hear about how my code helps you ;) 927 928This module is (C) Copyright by Tels http://bloodgate.com 2000-2003. 929 930=cut 931