diff options
Diffstat (limited to 'MDK/Common')
-rw-r--r-- | MDK/Common/DataStructure.pm | 178 | ||||
-rw-r--r-- | MDK/Common/File.pm | 318 | ||||
-rw-r--r-- | MDK/Common/Func.pm | 333 | ||||
-rw-r--r-- | MDK/Common/Math.pm | 197 | ||||
-rw-r--r-- | MDK/Common/String.pm | 164 | ||||
-rw-r--r-- | MDK/Common/System.pm | 478 | ||||
-rw-r--r-- | MDK/Common/Various.pm | 140 |
7 files changed, 0 insertions, 1808 deletions
diff --git a/MDK/Common/DataStructure.pm b/MDK/Common/DataStructure.pm deleted file mode 100644 index 79e4aa0..0000000 --- a/MDK/Common/DataStructure.pm +++ /dev/null @@ -1,178 +0,0 @@ -package MDK::Common::DataStructure; - -=head1 NAME - -MDK::Common::DataStructure - miscellaneous list/hash manipulation functions - -=head1 SYNOPSIS - - use MDK::Common::DataStructure qw(:all); - -=head1 EXPORTS - -=over - -=item sort_numbers(LIST) - -numerical sort (small numbers at beginning) - -=item ikeys(HASH) - -aka I<sorted integer keys>, as simple as C<sort { $a E<lt>=E<gt> $b } keys> - -=item add2hash(HASH REF, HASH REF) - -adds to the first hash the second hash if the key/value is not already there - -=item add2hash_ - -adds to the first hash the second hash if the key is not already there - -=item put_in_hash - -adds to the first hash the second hash, crushing existing key/values - -=item member(SCALAR, LIST) - -is the value in the list? - -=item invbool(SCALAR REF) - -toggles the boolean value - -=item listlength(LIST) - -returns the length of the list. Useful in list (opposed to array) context: - - sub f { "a", "b" } - my $l = listlength f(); - -whereas C<scalar f()> would return "b" - -=item deref(REF) - -de-reference - -=item deref_array(REF) - -de-reference arrays: - - deref_array [ "a", "b" ] #=> ("a", "b") - deref_array "a" #=> "a" - -=item is_empty_array_ref(SCALAR) - -is the scalar undefined or is the array empty - -=item is_empty_hash_ref(SCALAR) - -is the scalar undefined or is the hash empty - -=item uniq(LIST) - -returns the list with no duplicates (keeping the first elements) - -=item uniq_ { CODE } LIST - -returns the list with no duplicates according to the scalar results of CODE on each element of LIST (keeping the first elements) - - uniq_ { $_->[1] } [ 1, "fo" ], [ 2, "fob" ], [ 3, "fo" ], [ 4, "bar" ] - -gives [ 1, "fo" ], [ 2, "fob" ], [ 4, "bar" ] - -=item difference2(ARRAY REF, ARRAY REF) - -returns the first list without the element of the second list - -=item intersection(ARRAY REF, ARRAY REF, ...) - -returns the elements which are in all lists - -=item next_val_in_array(SCALAR, ARRAY REF) - -finds the value that follow the scalar in the list (circular): -C<next_val_in_array(3, [1, 2, 3])> gives C<1> -(do not use a list with duplicates) - -=item group_by2(LIST) - -interprets the list as an ordered hash, returns a list of [key,value]: -C<group_by2(1 => 2, 3 => 4, 5 => 6)> gives C<[1,2], [3,4], [5,6]> - -=item list2kv(LIST) - -interprets the list as an ordered hash, returns the keys and the values: -C<list2kv(1 => 2, 3 => 4, 5 => 6)> gives C<[1,3,5], [2,4,6]> - -=back - -=head1 SEE ALSO - -L<MDK::Common> - -=cut - - -use MDK::Common::Math; -use MDK::Common::Func; - - -use Exporter; -our @ISA = qw(Exporter); -our @EXPORT_OK = qw(sort_numbers ikeys add2hash add2hash_ put_in_hash member invbool listlength deref deref_array is_empty_array_ref is_empty_hash_ref uniq uniq_ difference2 intersection next_val_in_array group_by2 list2kv); -our %EXPORT_TAGS = (all => [ @EXPORT_OK ]); - - -sub sort_numbers { sort { $a <=> $b } @_ } -sub ikeys { my %l = @_; sort { $a <=> $b } keys %l } -sub put_in_hash { my ($a, $b) = @_; while (my ($k, $v) = each %{$b || {}}) { $a->{$k} = $v } $a } -sub add2hash { my ($a, $b) = @_; while (my ($k, $v) = each %{$b || {}}) { $a->{$k} ||= $v } $a } -sub add2hash_ { my ($a, $b) = @_; while (my ($k, $v) = each %{$b || {}}) { exists $a->{$k} or $a->{$k} = $v } $a } -sub member { my $e = shift; foreach (@_) { $e eq $_ and return 1 } 0 } -sub invbool { my $a = shift; $$a = !$$a; $$a } -sub listlength { scalar @_ } -sub strcpy { substr($_[0], $_[2] || 0, length $_[1]) = $_[1] } -sub deref { ref($_[0]) eq "ARRAY" ? @{$_[0]} : ref($_[0]) eq "HASH" ? %{$_[0]} : $_[0] } -sub deref_array { ref($_[0]) eq "ARRAY" ? @{$_[0]} : $_[0] } - -sub is_empty_array_ref { my $a = shift; !defined $a || @$a == 0 } -sub is_empty_hash_ref { my $a = shift; !defined $a || keys(%$a) == 0 } - -sub uniq { my %l; $l{$_} = 1 foreach @_; grep { delete $l{$_} } @_ } -sub difference2 { my %l; @l{@{$_[1]}} = (); grep { !exists $l{$_} } @{$_[0]} } -sub intersection { my (%l, @m); @l{@{shift @_}} = (); foreach (@_) { @m = grep { exists $l{$_} } @$_; %l = (); @l{@m} = () } keys %l } - -sub uniq_(&@) { - my $f = shift; - my %l; - $l{$f->($_)} = 1 foreach @_; - grep { delete $l{$f->($_)} } @_; -} - - -sub next_val_in_array { - my ($v, $l) = @_; - my %l = MDK::Common::Func::mapn(sub { @_ }, $l, [ @$l[1..$#$l], $l->[0] ]); - $l{$v}; -} - - -sub list2kv { - my (@k, @v); - for (my $i = 0; $i < @_; $i += 2) { - push @k, $_[$i + 0]; - push @v, $_[$i + 1]; - } - \@k, \@v; -} - -sub group_by2 { - my @l; - for (my $i = 0; $i < @_; $i += 2) { - push @l, [ $_[$i], $_[$i+1] ]; - } - @l; -} - - -1; diff --git a/MDK/Common/File.pm b/MDK/Common/File.pm deleted file mode 100644 index 1924931..0000000 --- a/MDK/Common/File.pm +++ /dev/null @@ -1,318 +0,0 @@ -package MDK::Common::File; - -=head1 NAME - -MDK::Common::File - miscellaneous file/filename manipulation functions - -=head1 SYNOPSIS - - use MDK::Common::File qw(:all); - -=head1 EXPORTS - -=over - -=item dirname(FILENAME) - -=item basename(FILENAME) - -returns the dirname/basename of the file name - -=item cat_(FILES) - -returns the files contents: in scalar context it returns a single string, in -array context it returns the lines. - -If no file is found, undef is returned - - -=item cat_or_die(FILENAME) - -same as C<cat_> but dies when something goes wrong - -=item cat__(FILEHANDLE REF) - -returns the file content: in scalar context it returns a single string, in -array context it returns the lines - -=item output(FILENAME, LIST) - -creates a file and outputs the list (if the file exists, it is clobbered) - -=item secured_output(FILENAME, LIST) - -likes output() but prevents insecured usage (it dies if somebody try -to exploit the race window between unlink() and creat()) - -=item append_to_file(FILENAME, LIST) - -add the LIST at the end of the file - -=item output_p(FILENAME, LIST) - -just like C<output> but creates directories if needed - -=item output_with_perm(FILENAME, PERMISSION, LIST) - -same as C<output_p> but sets FILENAME permission to PERMISSION (using chmod) - -=item mkdir_p(DIRNAME) - -creates the directory (make parent directories as needed) - -=item rm_rf(FILES) - -remove the files (including sub-directories) - -=item cp_f(FILES, DEST) - -just like "cp -f" - -=item cp_af(FILES, DEST) - -just like "cp -af" - -=item linkf(SOURCE, DESTINATION) - -=item symlinkf(SOURCE, DESTINATION) - -=item renamef(SOURCE, DESTINATION) - -same as link/symlink/rename but removes the destination file first - -=item touch(FILENAME) - -ensure the file exists, set the modification time to current time - -=item all(DIRNAME) - -returns all the file in directory (except "." and "..") - -=item all_files_rec(DIRNAME) - -returns all the files in directory and the sub-directories (except "." and "..") - -=item glob_(STRING) - -simple version of C<glob>: doesn't handle wildcards in directory (eg: -*/foo.c), nor special constructs (eg: [0-9] or {a,b}) - -=item substInFile { CODE } FILENAME - -executes the code for each line of the file. You can know the end of the file -is reached using C<eof> - -=item expand_symlinks(FILENAME) - -expand the symlinks in the absolute filename: -C<expand_symlinks("/etc/X11/X")> gives "/usr/X11R6/bin/XFree86" - -=item openFileMaybeCompressed(FILENAME) - -opens the file and returns the file handle. If the file is not found, tries to -gunzip the file + .gz - -=item catMaybeCompressed(FILENAME) - -cat_ alike. If the file is not found, tries to gunzip the file + .gz - -=back - -=head1 SEE ALSO - -L<MDK::Common> - -=cut - - -use Exporter; -our @ISA = qw(Exporter); -our @EXPORT_OK = qw(dirname basename cat_ cat_or_die cat__ output output_p output_with_perm append_to_file linkf symlinkf renamef mkdir_p rm_rf cp_f cp_af touch all all_files_rec glob_ substInFile expand_symlinks openFileMaybeCompressed catMaybeCompressed); -our %EXPORT_TAGS = (all => [ @EXPORT_OK ]); - -sub dirname { local $_ = shift; s|[^/]*/*\s*$||; s|(.)/*$|$1|; $_ || '.' } -sub basename { local $_ = shift; s|/*\s*$||; s|.*/||; $_ } -sub cat_ { my @l = map { my $F; open($F, '<', $_) ? <$F> : () } @_; wantarray() ? @l : join '', @l } -sub cat_or_die { open(my $F, '<', $_[0]) or die "can't read file $_[0]: $!\n"; my @l = <$F>; wantarray() ? @l : join '', @l } -sub cat__ { my ($f) = @_; my @l = <$f>; wantarray() ? @l : join '', @l } -sub output { my $f = shift; open(my $F, ">$f") or die "output in file $f failed: $!\n"; print $F $_ foreach @_; 1 } -sub append_to_file { my $f = shift; open(my $F, ">>$f") or die "output in file $f failed: $!\n"; print $F $_ foreach @_; 1 } -sub output_p { my $f = shift; mkdir_p(dirname($f)); output($f, @_) } -sub output_with_perm { my ($f, $perm, @l) = @_; mkdir_p(dirname($f)); output($f, @l); chmod $perm, $f } -sub linkf { unlink $_[1]; link $_[0], $_[1] } -sub symlinkf { unlink $_[1]; symlink $_[0], $_[1] } -sub renamef { unlink $_[1]; rename $_[0], $_[1] } - -sub secured_output { - my ($f, @l) = @_; - require POSIX; - unlink($f); - sysopen(my $F, $f, POSIX::O_CREAT() | POSIX::O_EXCL() | POSIX::O_RDWR()) or die "secure output in file $f failed: $! $@\n"; - print $F $_ foreach @l; - 1; -} - -sub mkdir_p { - my ($dir) = @_; - if (-d $dir) { - # nothing to do - } elsif (-e $dir) { - die "mkdir: error creating directory $dir: $dir is a file and i won't delete it\n"; - } else { - mkdir_p(dirname($dir)); - mkdir($dir, 0755) or die "mkdir: error creating directory $dir: $!\n"; - } - 1; -} - -sub rm_rf { - foreach (@_) { - if (!-l $_ && -d $_) { - rm_rf(glob_($_)); - rmdir($_) or die "can't remove directory $_: $!\n"; - } else { - unlink $_ or die "rm of $_ failed: $!\n"; - } - } - 1; -} - -sub cp_with_option { - my $option = shift @_; - my $keep_special = $option =~ /a/; - - my $dest = pop @_; - - @_ or return; - @_ == 1 || -d $dest or die "cp: copying multiple files, but last argument ($dest) is not a directory\n"; - - foreach my $src (@_) { - my $dest = $dest; - -d $dest and $dest .= '/' . basename($src); - - unlink $dest; - - if (-l $src && $keep_special) { - unless (symlink(readlink($src) || die("readlink failed: $!"), $dest)) { - warn "symlink: can't create symlink $dest: $!\n"; - } - } elsif (-d $src) { - -d $dest or mkdir $dest, (stat($src))[2] or die "mkdir: can't create directory $dest: $!\n"; - cp_with_option($option, glob_($src), $dest); - } elsif ((-b $src || -c $src) && $keep_special) { - my @stat = stat($src); - require MDK::Common::System; - MDK::Common::System::syscall_('mknod', $dest, $stat[2], $stat[6]) or die "mknod failed (dev $dest): $!"; - } else { - open(my $F, $src) or die "can't open $src for reading: $!\n"; - open(my $G, "> $dest") or die "can't cp to file $dest: $!\n"; - local $_; while (<$F>) { print $G $_ } - chmod((stat($src))[2], $dest); - } - } - 1; -} - -sub cp_f { cp_with_option('f', @_) } -sub cp_af { cp_with_option('af', @_) } - -sub touch { - my ($f) = @_; - unless (-e $f) { - my $F; - open($F, ">$f"); - } - my $now = time(); - utime $now, $now, $f; -} - - -sub all { - my $d = shift; - - local *F; - opendir F, $d or return; - my @l = grep { $_ ne '.' && $_ ne '..' } readdir F; - closedir F; - - @l; -} - -sub all_files_rec { - my ($d) = @_; - - map { $_, -d $_ ? all_files_rec($_) : () } map { "$d/$_" } all($d); -} - -sub glob_ { - my ($d, $f) = $_[0] =~ /\*/ ? (dirname($_[0]), basename($_[0])) : ($_[0], '*'); - - $d =~ /\*/ and die "glob_: wildcard in directory not handled ($_[0])\n"; - ($f = quotemeta $f) =~ s/\\\*/.*/g; - - $d =~ m|/$| or $d .= '/'; - map { $d eq './' ? $_ : "$d$_" } grep { /^$f$/ } all($d); -} - - -sub substInFile(&@) { - my ($f, $file) = @_; - my $linkdest; - #- try hard to keep symlinks as they were set - if (-l $file) { - my $targetfile = readlink $file; - unlink $file; - $linkdest = $file; - $file = $targetfile; - } - if (-s $file) { - local @ARGV = $file; - local $^I = ''; - local $_; - while (<>) { - $_ .= "\n" if eof && !/\n/; - &$f($_); - print; - } - } else { - local *F; my $old = select F; # that way eof return true - local $_ = ''; - &$f($_); - select $old; - eval { output($file, $_) }; - } - $linkdest and symlink $file, $linkdest; -} - - -sub concat_symlink { - my ($f, $l) = @_; - $l =~ m|^\.\./(/.*)| and return $1; - - $f =~ s|/$||; - while ($l =~ s|^\.\./||) { - $f =~ s|/[^/]+$|| or die "concat_symlink: $f $l\n"; - } - "$f/$l"; -} -sub expand_symlinks { - my ($first, @l) = split '/', $_[0]; - $first eq '' or die "expand_symlinks: $_[0] is relative\n"; - my ($f, $l); - foreach (@l) { - $f .= "/$_"; - $f = concat_symlink($f, "../$l") while $l = readlink $f; - } - $f; -} - - -sub openFileMaybeCompressed { - my ($f) = @_; - -e $f || -e "$f.gz" or die "file $f not found"; - open(my $F, -e $f ? $f : "gzip -dc '$f.gz'|") or die "file $f is not readable"; - $F; -} -sub catMaybeCompressed { cat__(openFileMaybeCompressed($_[0])) } - -1; diff --git a/MDK/Common/Func.pm b/MDK/Common/Func.pm deleted file mode 100644 index 82811bb..0000000 --- a/MDK/Common/Func.pm +++ /dev/null @@ -1,333 +0,0 @@ -package MDK::Common::Func; - -=head1 NAME - -MDK::Common::Func - miscellaneous functions - -=head1 SYNOPSIS - - use MDK::Common::Func qw(:all); - -=head1 EXPORTS - -=over - -=item may_apply(CODE REF, SCALAR) - -C<may_apply($f, $v)> is C<$f ? $f-E<gt>($v) : $v> - -=item may_apply(CODE REF, SCALAR, SCALAR) - -C<may_apply($f, $v, $otherwise)> is C<$f ? $f-E<gt>($v) : $otherwise> - -=item if_(BOOL, LIST) - -special constructs to workaround a missing perl feature: -C<if_($b, "a", "b")> is C<$b ? ("a", "b") : ()> - -example of use: C<f("a", if_(arch() =~ /i.86/, "b"), "c")> which is not the -same as C<f("a", arch()=~ /i.86/ && "b", "c")> - -=item if__(SCALAR, LIST) - -if_ alike. Test if the value is defined - -=item fold_left { CODE } LIST - -if you don't know fold_left (aka foldl), don't use it ;p - - fold_left { $::a + $::b } 1, 3, 6 - -gives 10 (aka 1+3+6) - -=item mapn { CODE } ARRAY REF, ARRAY REF, ... - -map lists in parallel: - - mapn { $_[0] + $_[1] } [1, 2], [2, 4] # gives 3, 6 - mapn { $_[0] + $_[1] + $_[2] } [1, 2], [2, 4], [3, 6] gives 6, 12 - -=item mapn_ { CODE } ARRAY REF, ARRAY REF, ... - -mapn alike. The difference is what to do when the lists have not the same -length: mapn takes the minimum common elements, mapn_ takes the maximum list -length and extend the lists with undef values - -=item find { CODE } LIST - -returns the first element where CODE returns true (or returns undef) - - find { /foo/ } "fo", "fob", "foobar", "foobir" - -gives "foobar" - -=item any { CODE } LIST - -returns 1 if CODE returns true for an element in LIST (otherwise returns 0) - - any { /foo/ } "fo", "fob", "foobar", "foobir" - -gives 1 - -=item every { CODE } LIST - -returns 1 if CODE returns true for B<every> element in LIST (otherwise returns 0) - - every { /foo/ } "fo", "fob", "foobar", "foobir" - -gives 0 - -=item map_index { CODE } LIST - -just like C<map>, but set C<$::i> to the current index in the list: - - map_index { "$::i $_" } "a", "b" - -gives "0 a", "1 b" - -=item each_index { CODE } LIST - -just like C<map_index>, but doesn't return anything - - each_index { print "$::i $_\n" } "a", "b" - -prints "0 a", "1 b" - -=item grep_index { CODE } LIST - -just like C<grep>, but set C<$::i> to the current index in the list: - - grep_index { $::i == $_ } 0, 2, 2, 3 - -gives (0, 2, 3) - -=item find_index { CODE } LIST - -returns the index of the first element where CODE returns true (or throws an exception) - - find_index { /foo/ } "fo", "fob", "foobar", "foobir" - -gives 2 - -=item map_each { CODE } HASH - -returns the list of results of CODE applied with $::a (key) and $::b (value) - - map_each { "$::a is $::b" } 1=>2, 3=>4 - -gives "1 is 2", "3 is 4" - -=item grep_each { CODE } HASH - -returns the hash key/value for which CODE applied with $::a (key) and $::b -(value) is true: - - grep_each { $::b == 2 } 1=>2, 3=>4, 4=>2 - -gives 1=>2, 4=>2 - -=item partition { CODE } LIST - -alike C<grep>, but returns both the list of matching elements and non matching elements - - my ($greater, $lower) = partition { $_ > 3 } 4, 2, 8, 0, 1 - -gives $greater = [ 4, 8 ] and $lower = [ 2, 0, 1 ] - -=item before_leaving { CODE } - -the code will be executed when the current block is finished - - # create $tmp_file - my $b = before_leaving { unlink $tmp_file }; - # some code that may throw an exception, the "before_leaving" ensures the - # $tmp_file will be removed - -=item cdie(SCALAR) - -aka I<conditional die>. If a C<cdie> is catched, the execution continues -B<after> the cdie, not where it was catched (as happens with die & eval) - -If a C<cdie> is not catched, it mutates in real exception that can be catched -with C<eval> - -cdie is useful when you want to warn about something weird, but when you can -go on. In that case, you cdie "something weird happened", and the caller -decide wether to go on or not. Especially nice for libraries. - -=item catch_cdie { CODE1 } sub { CODE2 } - -If a C<cdie> occurs while executing CODE1, CODE2 is executed. If CODE2 -returns true, the C<cdie> is catched. - -=back - -=head1 SEE ALSO - -L<MDK::Common> - -=cut - -use MDK::Common::Math; - - -use Exporter; -our @ISA = qw(Exporter); -our @EXPORT_OK = qw(may_apply if_ if__ fold_left mapn mapn_ find any every map_index each_index grep_index find_index map_each grep_each partition before_leaving catch_cdie cdie); -our %EXPORT_TAGS = (all => [ @EXPORT_OK ]); - - -sub may_apply { $_[0] ? $_[0]->($_[1]) : (@_ > 2 ? $_[2] : $_[1]) } - -# prototype is needed for things like: if_(/foo/, bar => 'boo') -sub if_($@) { - my $b = shift; - $b or return (); - wantarray() || @_ <= 1 or die("if_ called in scalar context with more than one argument " . join(":", caller())); - wantarray() ? @_ : $_[0]; -} -sub if__($@) { - my $b = shift; - defined $b or return (); - wantarray() || @_ <= 1 or die("if_ called in scalar context with more than one argument " . join(":", caller())); - wantarray() ? @_ : $_[0]; -} - -sub fold_left(&@) { - my ($f, $initial, @l) = @_; - local ($::a, $::b); - $::a = $initial; - foreach (@l) { $::b = $_; $::a = &$f() } - $::a; -} - -sub smapn { - my $f = shift; - my $n = shift; - my @r; - for (my $i = 0; $i < $n; $i++) { push @r, &$f(map { $_->[$i] } @_) } - @r; -} -sub mapn(&@) { - my $f = shift; - smapn($f, MDK::Common::Math::min(map { scalar @$_ } @_), @_); -} -sub mapn_(&@) { - my $f = shift; - smapn($f, MDK::Common::Math::max(map { scalar @$_ } @_), @_); -} - -sub find(&@) { - my $f = shift; - $f->($_) and return $_ foreach @_; - undef; -} -sub any(&@) { - my $f = shift; - $f->($_) and return 1 foreach @_; - 0; -} -sub every(&@) { - my $f = shift; - $f->($_) or return 0 foreach @_; - 1; -} - -sub map_index(&@) { - my $f = shift; - my @v; local $::i = 0; - map { @v = $f->(); $::i++; @v } @_; -} -sub each_index(&@) { - my $f = shift; - local $::i = 0; - foreach (@_) { - $f->(); - $::i++; - } -} -sub grep_index(&@) { - my $f = shift; - my $v; local $::i = 0; - grep { $v = $f->(); $::i++; $v } @_; -} -sub find_index(&@) { - my $f = shift; - local $_; - for (my $i = 0; $i < @_; $i++) { - $_ = $_[$i]; - &$f and return $i; - } - die "find_index failed in @_"; -} -sub map_each(&%) { - my ($f, %h) = @_; - my @l; - local ($::a, $::b); - while (($::a, $::b) = each %h) { push @l, &$f($::a, $::b) } - @l; -} -sub grep_each(&%) { - my ($f, %h) = @_; - my %l; - local ($::a, $::b); - while (($::a, $::b) = each %h) { $l{$::a} = $::b if &$f($::a, $::b) } - %l; -} -sub partition(&@) { - my $f = shift; - my (@a, @b); - foreach (@_) { - $f->($_) ? push(@a, $_) : push(@b, $_); - } - \@a, \@b; -} - -sub add_f4before_leaving { - my ($f, $b, $name) = @_; - - unless ($MDK::Common::Func::before_leaving::{$name}) { - no strict 'refs'; - ${"MDK::Common::Func::before_leaving::$name"} = 1; - ${"MDK::Common::Func::before_leaving::list"} = 1; - } - local *N = *{$MDK::Common::Func::before_leaving::{$name}}; - my $list = *MDK::Common::Func::before_leaving::list; - $list->{$b}{$name} = $f; - *N = sub { - my $f = $list->{$_[0]}{$name} or die ''; - $name eq 'DESTROY' and delete $list->{$_[0]}; - &$f; - } if !defined &{*N}; - -} - -#- ! the functions are not called in the order wanted, in case of multiple before_leaving :( -sub before_leaving(&) { - my ($f) = @_; - my $b = bless {}, 'MDK::Common::Func::before_leaving'; - add_f4before_leaving($f, $b, 'DESTROY'); - $b; -} - -sub catch_cdie(&&) { - my ($f, $catch) = @_; - - local @MDK::Common::Func::cdie_catches; - unshift @MDK::Common::Func::cdie_catches, $catch; - &$f(); -} - -sub cdie { - my ($err) = @_; - foreach (@MDK::Common::Func::cdie_catches) { - $@ = $err; - if (my $v = $_->(\$err)) { - return $v; - } - } - die $err; -} - -1; - diff --git a/MDK/Common/Math.pm b/MDK/Common/Math.pm deleted file mode 100644 index 5ed9a61..0000000 --- a/MDK/Common/Math.pm +++ /dev/null @@ -1,197 +0,0 @@ -package MDK::Common::Math; - -=head1 NAME - -MDK::Common::Math - miscellaneous math functions - -=head1 SYNOPSIS - - use MDK::Common::Math qw(:all); - -=head1 EXPORTS - -=over - -=item $PI - -the well-known constant - -=item even(INT) - -=item odd(INT) - -is the number even or odd? - -=item sqr(FLOAT) - -C<sqr(3)> gives C<9> - -=item sign(FLOAT) - -returns a value in { -1, 0, 1 } - -=item round(FLOAT) - -C<round(1.2)> gives C<1>, C<round(1.6)> gives C<2> - -=item round_up(FLOAT, INT) - -returns the number rounded up to the modulo: -C<round_up(11,10)> gives C<20> - -=item round_down(FLOAT, INT) - -returns the number rounded down to the modulo: -C<round_down(11,10)> gives C<10> - -=item divide(INT, INT) - -integer division (which is lacking in perl). In array context, also returns the remainder: -C<($a, $b) = divide(10,3)> gives C<$a is 3> and C<$b is 1> - -=item min(LIST) - -=item max(LIST) - -returns the minimum/maximum number in the list - -=item or_(LIST) - -is there a true value in the list? - -=item and_(LIST) - -are all values true in the list? - -=item sum(LIST) - -=item product(LIST) - -returns the sum/product of all the element in the list - -=item factorial(INT) - -C<factorial(4)> gives C<24> (4*3*2) - -=back - -=head1 OTHER - -the following functions are provided, but not exported: - -=over - -=item factorize(INT) - -C<factorize(40)> gives C<([2,3], [5,1])> as S<40 = 2^3 + 5^1> - -=item decimal2fraction(FLOAT) - -C<decimal2fraction(1.3333333333)> gives C<(4, 3)> -($PRECISION is used to decide which precision to use) - -=item poly2(a,b,c) - -Solves the a*x2+b*x+c=0 polynomial: -C<poly2(1,0,-1)> gives C<(1, -1)> - -=item permutations(n,p) - -A(n,p) - -=item combinaisons(n,p) - -C(n,p) - -=back - -=head1 SEE ALSO - -L<MDK::Common> - -=cut - - -use Exporter; -our @ISA = qw(Exporter); -our @EXPORT_OK = qw($PI even odd sqr sign round round_up round_down divide min max or_ and_ sum product factorial); -our %EXPORT_TAGS = (all => [ @EXPORT_OK ]); - - -our $PRECISION = 10; -our $PI = 3.1415926535897932384626433832795028841972; - -sub even { $_[0] % 2 == 0 } -sub odd { $_[0] % 2 == 1 } -sub sqr { $_[0] * $_[0] } -sub sign { $_[0] <=> 0 } -sub round { int($_[0] + 0.5) } -sub round_up { my ($i, $r) = @_; $i = int $i; $i += $r - ($i + $r - 1) % $r - 1 } -sub round_down { my ($i, $r) = @_; $i = int $i; $i -= $i % $r } -sub divide { my $d = int $_[0] / $_[1]; wantarray() ? ($d, $_[0] % $_[1]) : $d } -sub min { my $n = shift; $_ < $n and $n = $_ foreach @_; $n } -sub max { my $n = shift; $_ > $n and $n = $_ foreach @_; $n } -sub or_ { my $n = 0; $n ||= $_ foreach @_; $n } -sub and_ { my $n = 1; $n &&= $_ foreach @_; $n } -sub sum { my $n = 0; $n += $_ foreach @_; $n } -sub product { my $n = 1; $n *= $_ foreach @_; $n } - - -sub factorize { - my ($n) = @_; - my @r; - - $n == 1 and return [ 1, 1 ]; - for (my $k = 2; sqr($k) <= $n; $k++) { - my $i = 0; - for ($i = 0; $n % $k == 0; $i++) { $n /= $k } - $i and push @r, [ $k, $i ]; - } - $n > 1 and push @r, [ $n, 1 ]; - @r; -} - -sub decimal2fraction { # ex: 1.33333333 -> (4, 3) - my $n0 = shift; - my $precision = 10 ** -(shift || $PRECISION); - my ($a, $b) = (int $n0, 1); - my ($c, $d) = (1, 0); - my $n = $n0 - int $n0; - my $k; - until (abs($n0 - $a / $c) < $precision) { - $n = 1 / $n; - $k = int $n; - ($a, $b) = ($a * $k + $b, $a); - ($c, $d) = ($c * $k + $d, $c); - $n -= $k; - } - ($a, $c); -} - -sub poly2 { - my ($a, $b, $c) = @_; - my $d = ($b**2 - 4 * $a * $c) ** 0.5; - (-$b + $d) / 2 / $a, (-$b - $d) / 2 / $a; -} - -# A(n,p) -sub permutations { - my ($n, $p) = @_; - my ($r, $i); - for ($r = 1, $i = 0; $i < $p; $i++) { - $r *= $n - $i; - } - $r; -} - -# C(n,p) -sub combinaisons { - my ($n, $p) = @_; - - permutations($n, $p) / factorial($p); -} - -sub factorial { permutations($_[0], $_[0]) } - - -1; diff --git a/MDK/Common/String.pm b/MDK/Common/String.pm deleted file mode 100644 index 40eee1d..0000000 --- a/MDK/Common/String.pm +++ /dev/null @@ -1,164 +0,0 @@ -package MDK::Common::String; - -=head1 NAME - -MDK::Common::String - formatting functions - -=head1 SYNOPSIS - - use MDK::Common::String qw(:all); - -=head1 EXPORTS - -=over - -=item bestMatchSentence(STRING, LIST) - -finds in the list the best corresponding string - -=item formatList(INT, LIST) - -if the list size is bigger than INT, replace the remaining elements with "...". - -formatList(3, qw(a b c d e)) # => "a, b, c, ..." - -=item formatError(STRING) - -the string is something like "error at foo.pl line 2" that you get when -catching an exception. formatError will remove the "at ..." so that you can -nicely display the returned string to the user - -=item formatTimeRaw(TIME) - -the TIME is an epoch as returned by C<time>, the formatted time looks like "23:59:00" - -=item formatLines(STRING) - -remove "\n"s when the next line doesn't start with a space. Otherwise keep -"\n"s to keep the indentation. - -=item formatAlaTeX(STRING) - -handle carriage return just like LaTeX: merge lines that are not separated by -an empty line - -=item begins_with(STRING, STRING) - -return true if first argument begins with the second argument. Use this -instead of regexps if you don't want regexps. - -begins_with("hello world", "hello") # => 1 - -=item warp_text(STRING, INT) - -return a list of lines which do not exceed INT characters -(or a string in scalar context) - -=item warp_text(STRING) - -warp_text at a default width (80) - -=back - -=head1 SEE ALSO - -L<MDK::Common> - -=cut - - -use Exporter; -our @ISA = qw(Exporter); -our @EXPORT_OK = qw(bestMatchSentence formatList formatError formatTimeRaw formatLines formatAlaTeX begins_with warp_text); -our %EXPORT_TAGS = (all => [ @EXPORT_OK ]); - - -# count the number of character that match -sub bestMatchSentence { - - my $best = -1; - my $bestSentence; - my @s = split /\W+/, shift; - foreach (@_) { - my $count = 0; - foreach my $e (@s) { - $count += length($e) if /^$e$/; - $count += length($e) if /^$e$/i; - $count += length($e) if /$e/; - $count += length($e) if /$e/i; - } - $best = $count, $bestSentence = $_ if $count > $best; - } - wantarray() ? ($bestSentence, $best) : $bestSentence; -} - - -sub formatList { - my $nb = shift; - join(", ", @_ <= $nb ? @_ : (@_[0..$nb-1], '...')); -} -sub formatError { - my ($err) = @_; - if (!$::testing) { - $err =~ s/Uncaught exception from user code:\n\t//s; #- happens with "use diagnostics" - $err =~ s/ at .*?$/./s; - } - $err; -} -sub formatTimeRaw { - my ($s, $m, $h) = gmtime($_[0]); - sprintf "%d:%02d:%02d", $h, $m, $s; -} -sub formatLines { - my ($t, $tmp); - foreach (split "\n", $_[0]) { - if (/^\s/) { - $t .= "$tmp\n"; - $tmp = $_; - } else { - $tmp = ($tmp ? "$tmp " : ($t && "\n") . $tmp) . $_; - } - } - "$t$tmp\n"; -} -sub formatAlaTeX { - my ($t, $tmp) = ('', ''); - foreach (split "\n", $_[0]) { - if (/^$/) { - $t .= ($t && "\n") . $tmp; - $tmp = ''; - } else { - $tmp = ($tmp && "$tmp ") . (/^\s*(.*?)\s*$/)[0]; - } - } - $t . ($t && $tmp && "\n") . $tmp; -} - - -sub begins_with { - my ($s, $prefix) = @_; - index($s, $prefix) == 0; -} - -sub warp_text { - my ($text, $o_width) = @_; - - my @l; - foreach (split "\n", $text) { - my ($beg) = /^(\s*)/; - my $t = ''; - foreach (split /\s+/, $_) { - if (length "$beg$t $_" > ($o_width || 80)) { - push @l, "$beg$t"; - $beg = ''; - $t = $_; - } else { - $t = $t ? "$t $_" : $_; - } - } - push @l, "$beg$t"; - } - wantarray() ? @l : join("\n", @l); -} - -1; diff --git a/MDK/Common/System.pm b/MDK/Common/System.pm deleted file mode 100644 index a947523..0000000 --- a/MDK/Common/System.pm +++ /dev/null @@ -1,478 +0,0 @@ -package MDK::Common::System; - -=head1 NAME - -MDK::Common::System - system-related useful functions - -=head1 SYNOPSIS - - use MDK::Common::System qw(:all); - -=head1 EXPORTS - -=over - -=item %compat_arch - -architecture compatibility mapping (eg: k6 => i586, k7 => k6 ...) - -=item %printable_chars - -7 bit ascii characters - -=item $sizeof_int - -sizeof(int) - -=item $bitof_int - -$sizeof_int * 8 - -=item arch() - -return the architecture (eg: i686, ppc, ia64, k7...) - -=item typeFromMagic(FILENAME, LIST) - -find the first corresponding magic in FILENAME. eg of LIST: - - [ 'empty', 0, "\0\0\0\0" ], - [ 'grub', 0, "\xEBG", 0x17d, "stage1 \0" ], - [ 'lilo', 0x2, "LILO" ], - -where each entry is [ magic_name, offset, string, offset, string, ... ]. - -=item list_passwd() - -return the list of users as given by C<getpwent> (see perlfunc) - -=item list_home() - -return the list of home (eg: /home/foo, /home/pixel, ...) - -=item list_skels() - -return the directories where we can find dot files: homes, /root and /etc/skel - -=item list_users() - -return the list of unprivilegied users (aka those whose uid is greater -than 500 and who are not "nobody"). - -=item syscall_(NAME, PARA) - -calls the syscall NAME - -=item psizeof(STRING) - -useful to know the length of a C<pack> format string. - - psizeof("I I I C C S") = 4 + 4 + 4 + 1 + 1 + 2 = 16 - -=item availableMemory() - -size of swap + memory - -=item availableRamMB() - -size of RAM as reported by the BIOS (it is a round number that can be -displayed or given as "mem=128M" to the kernel) - -!! "mem=..." is dangerous in 2.4 kernels - -=item gettimeofday() - -returns the epoch in microseconds - -=item unix2dos(STRING) - -takes care of CR/LF translation - -=item whereis_binary(STRING) - -return the first absolute file in $PATH (similar to which(1) and whereis(1)) - -=item getVarsFromSh(FILENAME) - -returns a hash associating shell variables to their value. useful for config -files such as /etc/sysconfig files - -=item setVarsInSh(FILENAME, HASH REF) - -write file in shell format association a shell variable + value for each -key/value - -=item setVarsInSh(FILENAME, HASH REF, LIST) - -restrict the fields that will be printed to LIST - -=item setVarsInShMode(FILENAME, INT, HASH REF, LIST) - -like setVarsInSh with INT being the chmod value for the config file - -=item addVarsInSh(FILENAME, HASH REF) - -like setVarsInSh but keeping the entries in the file - -=item addVarsInSh(FILENAME, HASH REF, LIST) - -like setVarsInSh but keeping the entries in the file - -=item addVarsInShMode(FILENAME, INT, HASH REF, LIST) - -like addVarsInShMode but keeping the entries in the file - -=item setExportedVarsInCsh(FILENAME, HASH REF, LIST) - -same as C<setExportedVarsInSh> for csh format - -=item template2file(FILENAME_IN, FILENAME_OUT, HASH) - -read in a template file, replace keys @@@key@@@ with value, save it in out -file - -=item template2userfile(PREFIX, FILENAME_IN, FILENAME_OUT, BOOL, HASH) - -read in a template file, replace keys @@@key@@@ with value, save it in every homes. -If BOOL is true, overwrite existing files. FILENAME_OUT must be a relative filename - -=item read_gnomekderc(FILENAME, STRING) - -reads GNOME-like and KDE-like config files (aka windows-like). -You must give a category. eg: - - read_gnomekderc("/etc/skels/.kderc", 'KDE') - -=item update_gnomekderc(FILENAME, STRING, HASH) - -modifies GNOME-like and KDE-like config files (aka windows-like). -If the category doesn't exist, it creates it. eg: - - update_gnomekderc("/etc/skels/.kderc", 'KDE', - kfmIconStyle => "Large") - -=item fuzzy_pidofs(REGEXP) - -return the list of process ids matching the regexp - -=back - -=head1 OTHER - -=over - -=item better_arch(ARCH1, ARCH2) - -is ARCH1 compatible with ARCH2? - -better_arch('i386', 'ia64') and better_arch('ia64', 'i386') are false - -better_arch('k7', 'k6') is true and better_arch('k6', 'k7') is false - -=item compat_arch(STRING) - -test the architecture compatibility. eg: - -compat_arch('i386') is false on a ia64 - -compat_arch('k6') is true on a k6 and k7 but false on a i386 and i686 - -=back - -=head1 SEE ALSO - -L<MDK::Common> - -=cut - - -use MDK::Common::Math; -use MDK::Common::File; - -use Exporter; -our @ISA = qw(Exporter); -our @EXPORT_OK = qw(%compat_arch $printable_chars $sizeof_int $bitof_int arch distrib typeFromMagic list_passwd list_home list_skels list_users syscall_ psizeof availableMemory availableRamMB gettimeofday unix2dos whereis_binary getVarsFromSh setVarsInSh setVarsInShMode addVarsInSh addVarsInShMode setExportedVarsInSh setExportedVarsInCsh template2file template2userfile read_gnomekderc update_gnomekderc fuzzy_pidofs); #); -our %EXPORT_TAGS = (all => [ @EXPORT_OK ]); - - -our %compat_arch = ( #- compatibilty arch mapping. - 'noarch' => undef, - 'ia32' => 'noarch', - 'i386' => 'ia32', - 'i486' => 'i386', - 'i586' => 'i486', - 'i686' => 'i586', - 'i786' => 'i686', - 'k6' => 'i586', - 'k7' => 'k6', - 'k8' => 'k7', - 'x86_64' => 'i686', - 'amd64' => 'x86_64', - 'ia64' => 'noarch', - 'ppc' => 'noarch', - 'alpha' => 'noarch', - 'sparc' => 'noarch', - 'sparc32' => 'sparc', - 'sparc64' => 'sparc32', - 'ia64' => 'noarch', - ); - -our $printable_chars = "\x20-\x7E"; -our $sizeof_int = psizeof("i"); -our $bitof_int = $sizeof_int * 8; - - -sub arch() { - my $SYS_NMLN = 65; - my $format = "Z$SYS_NMLN" x 6; - my $t = pack $format; - syscall_('uname', $t); - (unpack($format, $t))[4]; -} -sub better_arch { - my ($new, $old) = @_; - while ($new && $new ne $old) { $new = $compat_arch{$new} } - $new; -} -sub compat_arch { better_arch(arch(), $_[0]) } - -sub distrib() { - my $release = MDK::Common::File::cat_('/etc/release'); - my ($real_system, $real_product) = $release =~ /(.*) release ([\d.]+)/; - my $oem_config = '/etc/sysconfig/oem'; - my %oem = -f $oem_config && getVarsFromSh($oem_config); - my $company = $oem{COMPANY} || 'Mandriva'; - my $system = $oem{SYSTEM} || $real_system; - my $product = $oem{PRODUCT} || $real_product; - (company => $company, system => $system, product => $product, real_system => $real_system, real_product => $real_product); -} - -sub typeFromMagic { - my $f = shift; - sysopen(my $F, $f, 0) or return; - - my $tmp; - M: foreach (@_) { - if (ref($_) eq 'CODE') { - my $name = $_->($F) or next M; - return $name; - } else { - my ($name, @l) = @$_; - while (@l) { - my ($offset, $signature) = splice(@l, 0, 2); - sysseek($F, $offset, 0) or next M; - sysread($F, $tmp, length $signature); - $tmp eq $signature or next M; - } - return $name; - } - } - undef; -} - - -sub list_passwd() { - my (@l, @e); - setpwent(); - while (@e = getpwent()) { push @l, [ @e ] } - endpwent(); - @l; -} -sub list_home() { - map { $_->[7] } grep { $_->[2] >= 500 } list_passwd(); -} -sub list_skels { - my ($prefix, $suffix) = @_; - grep { -d $_ && -w $_ } map { "$prefix$_/$suffix" } '/etc/skel', '/root', list_home(); -} - -sub list_users() { - map { 500 <= $_->[2] && $_->[0] ne "nobody" ? $_->[0] : () } list_passwd(); -} - - - -sub syscall_ { - my $f = shift; - - #- load syscall.ph in package "main". If every use of syscall.ph do the same, all will be nice - package main; - require 'syscall.ph'; - - syscall(&{"main::SYS_$f"}, @_) == 0; -} - - -#- return the size of the partition and its free space in KiB -sub df { - my ($mntpoint) = @_; - my ($blocksize, $size, $free); - my $buf = ' ' x 20000; - syscall_('statfs', $mntpoint, $buf) or return; - (undef, $blocksize, $size, $free, undef, undef) = unpack "L!6", $buf; - map { $_ * ($blocksize / 1024) } $size, $free; -} - -sub sync() { syscall_('sync') } -sub psizeof { length pack $_[0] } -sub availableMemory() { MDK::Common::Math::sum(map { /(\d+)/ } grep { /^(MemTotal|SwapTotal):/ } MDK::Common::File::cat_("/proc/meminfo")) } -sub availableRamMB() { 4 * MDK::Common::Math::round((-s '/proc/kcore') / 1024 / 1024 / 4) } -sub gettimeofday() { my $t = pack "LL"; syscall_('gettimeofday', $t, 0) or die "gettimeofday failed: $!\n"; unpack("LL", $t) } -sub unix2dos { local $_ = $_[0]; s/\015$//mg; s/$/\015/mg; $_ } - -sub whereis_binary { - my ($prog, $o_prefix) = @_; - if ($prog =~ m!/!) { - warn qq(don't call whereis_binary with a name containing a "/" (the culprit is: $prog)\n); - return; - } - foreach (split(':', $ENV{PATH})) { - my $f = "$_/$prog"; - -x "$o_prefix$f" and return $f; - } -} - -sub getVarsFromSh { - my %l; - open(my $F, $_[0]) or return; - local $_; - while (<$F>) { - s/#.*//; # remove comments - s/^\s*//; # leading space - my ($v, $val) = /^(\w+)=(.*)/ or next; - $val = $1 if $val =~ /^"(.*)"$/ || $val =~ /^'(.*)'$/; - $l{$v} = $val; - } - %l; -} - -sub addVarsInSh { - my ($file, $l, @fields) = @_; - addVarsInShMode($file, 0777 ^ umask(), $l, @fields); -} - -sub addVarsInShMode { - my ($file, $mod, $l, @fields) = @_; - my %l = @fields ? map { $_ => $l->{$_} } @fields : %$l; - my %l2 = getVarsFromSh($file); - - # below is add2hash_(\%l, \%l2); - exists $l{$_} or $l{$_} = $l2{$_} foreach keys %l2; - - setVarsInShMode($file, $mod, \%l); -} - -sub setVarsInSh { - my ($file, $l, @fields) = @_; - setVarsInShMode($file, 0777 ^ umask(), $l, @fields); -} - -sub setVarsInShMode { - my ($file, $mod, $l, @fields) = @_; - @fields = keys %$l unless @fields; - my $string = join('', - map { - my $val = $l->{$_}; - if ($val =~ /["`\$]/) { - $val =~ s/(')/\\$1/g; - $val = qq('$val'); - } elsif ($val =~ /['|\s\\]/) { - $val =~ s/(["\\])/\\$1/g; - $val = qq("$val"); - } - "$_=$val\n"; - } grep { $l->{$_} } @fields - ); - if ($file =~ m!^/home/!) { - MDK::Common::File::secured_output($file, $string); - } else { - MDK::Common::File::output($file, $string); - } - - chmod $mod, $file; -} - -sub setExportedVarsInSh { - my ($file, $l, @fields) = @_; - @fields = keys %$l unless @fields; - - MDK::Common::File::output($file, - (map { $l->{$_} ? "$_=$l->{$_}\n" : () } @fields), - @fields ? "export " . join(" ", @fields) . "\n" : (), - ); -} - -sub setExportedVarsInCsh { - my ($file, $l, @fields) = @_; - @fields = keys %$l unless @fields; - - MDK::Common::File::output($file, map { $l->{$_} ? "setenv $_ $l->{$_}\n" : () } @fields); -} - -sub template2file { - my ($in, $out, %toreplace) = @_; - MDK::Common::File::output($out, map { s/@@@(.*?)@@@/$toreplace{$1}/g; $_ } MDK::Common::File::cat_($in)); -} -sub template2userfile { - my ($prefix, $in, $out_rel, $force, %toreplace) = @_; - - foreach (list_skels($prefix, $out_rel)) { - -d MDK::Common::File::dirname($_) or !-e $_ or $force or next; - - template2file($in, $_, %toreplace); - m|/home/(.+?)/| and chown(getpwnam($1), getgrnam($1), $_); - } -} - -sub read_gnomekderc { - my ($file, $category) = @_; - my %h; - foreach (MDK::Common::File::cat_($file), "[NOCATEGORY]\n") { - if (/^\s*\[\Q$category\E\]/i ... /^\[/) { - $h{$1} = $2 if /^\s*([^=]*?)=(.*)/; - } - } - %h; -} - -sub update_gnomekderc { - my ($file, $category, %subst_) = @_; - - my %subst = map { lc($_) => [ $_, $subst_{$_} ] } keys %subst_; - - my $s; - defined($category) or $category = "DEFAULTCATEGORY"; - foreach ("[DEFAULTCATEGORY]\n", MDK::Common::File::cat_($file), "[NOCATEGORY]\n") { - if (my $i = /^\s*\[\Q$category\E\]/i ... /^\[/) { - if ($i =~ /E/) { #- for last line of category - chomp $s; $s .= "\n"; - $s .= "$_->[0]=$_->[1]\n" foreach values %subst; - %subst = (); - } elsif (/^\s*([^=]*?)=/) { - if (my $e = delete $subst{lc($1)}) { - $_ = "$1=$e->[1]\n"; - } - } - } - $s .= $_ if !/^\[(NO|DEFAULT)CATEGORY\]/; - } - - #- if category has not been found above (DEFAULTCATEGORY is always found). - if (keys %subst) { - chomp $s; - $s .= "\n[$category]\n"; - $s .= "$_->[0]=$_->[1]\n" foreach values %subst; - } - - MDK::Common::File::output_p($file, $s); - -} - -sub fuzzy_pidofs { - my ($regexp) = @_; - grep { - /^(\d+)$/ && (MDK::Common::File::cat_("/proc/$_/cmdline") || readlink("/proc/$_/exe") || '') =~ /$regexp/; - } MDK::Common::File::all('/proc'); -} - -1; diff --git a/MDK/Common/Various.pm b/MDK/Common/Various.pm deleted file mode 100644 index 96e76d3..0000000 --- a/MDK/Common/Various.pm +++ /dev/null @@ -1,140 +0,0 @@ -package MDK::Common::Various; - -=head1 NAME - -MDK::Common::Various - miscellaneous functions - -=head1 SYNOPSIS - - use MDK::Common::Various qw(:all); - -=head1 EXPORTS - -=over - -=item first(LIST) - -returns the first value. C<first(XXX)> is an alternative for C<((XXX)[0])> - -=item second(LIST) - -returns the second value. C<second(XXX)> is an alternative for C<((XXX)[1])> - -=item top(LIST) - -returns the last value. C<top(@l)> is an alternative for C<$l[$#l]> - -=item to_bool(SCALAR) - -returns a value in { 0, 1 } - -=item to_int(STRING) - -extracts the number from the string. You could use directly C<int "11 foo">, but -you'll get I<Argument "11 foo" isn't numeric in int>. It also handles returns -11 for C<"foo 11 bar"> - -=item to_float(STRING) - -extract a decimal number from the string - -=item bool2text(SCALAR) - -returns a value in { "true", "false" } - -=item bool2yesno(SCALAR) - -returns a value in { "yes", "no" } - -=item text2bool(STRING) - -inverse of C<bool2text> and C<bool2yesno> - -=item chomp_(STRING) - -non-mutable version of chomp: do not modify the argument, returns the chomp'ed -value. Also works on lists: C<chomp_($a, $b)> is equivalent to -C<chomp($a) ; chomp($b) ; ($a,$b)> - -=item backtrace() - -returns a string describing the backtrace. eg: - - sub g { print "oops\n", backtrace() } - sub f { &g } - f(); - -gives - - oops - main::g() called from /tmp/t.pl:2 - main::f() called from /tmp/t.pl:4 - - -=item internal_error(STRING) - -another way to C<die> with a nice error message and a backtrace - -=item noreturn() - -use this to ensure nobody uses the return value of the function. eg: - - sub g { print "g called\n"; noreturn } - sub f { print "g returns ", g() } - f(); - -gives - - test.pl:3: main::f() expects a value from main::g(), but main::g() doesn't return any value - -=back - -=head1 SEE ALSO - -L<MDK::Common> - -=cut - - -use Exporter; -our @ISA = qw(Exporter); -our @EXPORT_OK = qw(first second top to_bool to_int to_float bool2text bool2yesno text2bool chomp_ backtrace internal_error noreturn); -our %EXPORT_TAGS = (all => [ @EXPORT_OK ]); - - -sub first { $_[0] } -sub second { $_[1] } -sub top { $_[-1] } - -sub to_bool { $_[0] ? 1 : 0 } -sub to_int { $_[0] =~ /\s*(\d*)/ && $1 } -sub to_float { $_[0] =~ /\s*(\d*(\.\d*)?)/ && $1 } -sub bool2text { $_[0] ? "true" : "false" } -sub bool2yesno { $_[0] ? "yes" : "no" } -sub text2bool { my $t = lc($_[0]); $t eq "true" || $t eq "yes" ? 1 : 0 } - -sub chomp_ { my @l = @_; chomp @l; wantarray() ? @l : $l[0] } - -sub backtrace() { - my $s; - for (my $i = 1; caller($i); $i++) { - my ($_package, $file, $line, $func) = caller($i); - $s .= "$func() called from $file:$line\n"; - } - $s; -} - -sub internal_error { - die "INTERNAL ERROR: $_[0]\n" . backtrace(); -} - -sub noreturn() { - if (defined wantarray()) { - my ($_package, $file, $line, $func) = caller(1); - my (undef, undef, undef, $func2) = caller(2); - die "$file:$line: $func2() expects a value from $func(), but $func() doesn't return any value\n"; - } -} - -1; - |