1  package Treemap::Input::DirSlashS;
  2
  3  use 5.006;
  4  use strict;
  5  use warnings;
  6  use Carp;
  7
  8  use File::Basename;
  9
 10  require Exporter;
 11  require Treemap::Input;
 12
 13  our @ISA = qw( Treemap::Input Exporter );
 14  our @EXPORT_OK = (  );
 15  our @EXPORT = qw( );
 16  our $VERSION = '0.01';
 17
 18  # ------------------------------------------
 19  # Methods:
 20  # ------------------------------------------
 21  sub new
 22  {
 23     my $classname = shift;
 24     my $self = $classname->SUPER::new( @_ );  # Call parent constructor
 25     $self->_init( @_ );  # Initialize child variables
 26     return $self;
 27  }
 28
 29  sub _init
 30  {
 31     my $self = shift;
 32  }
 33
 34  sub load
 35  {
 36     my $self = shift;
 37     my( $filename ) = @_;
 38
 39     open( FH, $filename ) || die "Couldn't open $filename";
 40
 41     # First we need to parse this nasty format, and turn it into something
 42     # computable
 43     my $data;
 44     my $present_dir;
 45     while( <FH> ) {
 46        next if /^[\n\r]$/;  # Skip blank lines
 47
 48        # Keep track of which directory we're in.
 49        if ( /^[    ]+Directory of ([^\n\r]*)/ ) {
 50           $present_dir = $1;
 51           next;
 52        }
 53        # Find the number of bytes in this directory.
 54        # This is also our end-of-record, so insert the present directory and
 55        # it's size into our data structure.
 56  #     elsif( /File\(s\)[   ]+([0-9,]+) bytes/ ) {
 57  #        my $bytes = $1;
 58  #        my $path = $present_dir;
 59        elsif ( /^([0-9]{2})\/([0-9]{2})\/([0-9]{4}).{10}[ ]+([0-9,]+) ([^\n\r]*)/ ) {
 60           my $path = "$present_dir\\$5";
 61           my $bytes = $4;
 62           $bytes =~ s/,//g;
 63           my @dirs = split (/\\/, $path );
 64           my $code = "\$data->{kids}->{\"" . join("\"}->{kids}->{\"", @dirs ) . "\"}->{size} = \"$bytes\";";
 65           eval( $code );
 66        }
 67     }
 68     # Traverse the resultant tree and convert it into a treemap data structure
 69     $self->{DATA} = $self->_TreemapForm( $data );
 70     $data = undef;
 71     if ( $self->{DATA} ) {
 72        return 1;
 73     }
 74     return 0;
 75  }
 76
 77  sub _TreemapForm {
 78     my $self = shift;
 79     my( $data, $name ) = @_;
 80     my $tree;
 81     $tree->{size} = $data->{size} || 0;
 82     $tree->{name} = $name || undef;
 83     if ( $name =~ /\.(.{0,3})$/ && length($1) > 0 ) {
 84        my ( $rr, $gg, $bb ) = split ( //, uc($1) );
 85        $rr = ord($rr); $gg = ord($gg); $bb = ord($bb);
 86        $rr==47?$rr=0:$rr=($rr - 47) / 42 * 256;
 87        $gg==47?$gg=0:$gg=($gg - 47) / 42 * 256;
 88        $bb==47?$bb=0:$bb=($bb - 47) / 42 * 256;
 89        $tree->{colour} = sprintf("#%2X%2X%2X", $rr, $gg, $bb );
 90     } else {
 91        $tree->{colour} = "#FFFFFF";
 92     }
 93     if ( defined($data->{kids}) ) {
 94        my @kids = ();
 95        foreach my $kid( keys(%{$data->{kids}}) ) {
 96           push( @kids, $self->_TreemapForm( $data->{kids}->{$kid}, $kid ) );
 97           $tree->{size} += $kids[@kids-1]->{size};
 98        }
 99        $tree->{children} = \@kids;
100     }
101     return $tree;
102  }
103  1;
104
105  __END__
106
107  # ------------------------------------------
108  # Documentation:
109  # ------------------------------------------
110
111  =head1 NAME
112
113  =over 4
114
115  =item Treemap::Input::DirSlashS
116
117  Creates an input object with methods suitable for use with a Treemap object.
118
119  =back 4
120
121  =head1 SYNOPSIS
122
123   #!/usr/bin/perl -w
124   use Treemap::Input::DirSlashS;
125   
126   my $dir = Treemap::Input::DirSlashS->new();
127   $dir->load( "/some/dir" );
128
129  =head1 DESCRIPTION
130
131  This class reads in a directory tree, and makes the data available for use to a
132  Treemap object.  Colour is based the the mtime of the files. Rectangle areas
133  are based on the size of the directory contents / files.
134
135  =head1 METHODS
136
137  =over 4
138
139  =item new( FOLLOW_SYMLINKS => (1|undef) )
140
141  Instantiate a new object
142
143  =item load( "filename.txt" )
144
145  Load the output of "dir /s > filname.txt".
146
147  =back 4
148
149  =head1 SEE ALSO
150
151  L<Treemap::Input>, L<Treemap>
152
153  =head1 AUTHORS
154
155  Simon Ditner <simon@uc.org>, and Eric Maki <eric@uc.org>
156
157  =head1 LICENSE
158
159  This library is free software; you can redistribute it and/or modify it under
160  the same terms as Perl itself.
161
162  =cut