# Usage example follows subroutines! # ------------------------------ # CaptureStructure -- subroutine STRICT # ------------------------------ # Author: rhardy@webcon.net # This function will capture a complex data structure (including # multi-dimensional hashes) and dump it to the specified file. # Function returns the datatype on success for easy error detection: # i.e. &CaptureStructure or die; # Syntax: &CaptureStructure($rComplexDataStructure, $FileToWrite); sub CaptureStructure { my $Donor = shift; my $File = shift; my ( $DNA, $Clone, $Length, $Offset, $Written, $RefType); $RefType=ref($Donor); local $Data::Dumper::Indent = 0; # It will be eval'd, we don't need pretty local $Data::Dumper::Purity = 1; # make sure all code is present local $Data::Dumper::Terse = 1; # makes the eval work well local $Data::Dumper::Deepcopy = 1; # tell Dumper our intent local $Data::Dumper::QuoteKeys = 1; # Insist on having our keys quoted or else some multidimensional arrays fail. # Interestingly enough, Dumper will embed the call to bless in the DNA. # Which makes this whole analogy really quite accurate and somehow strange # WARNING: As of V2.101 the Dumper function does NOT properly quote hash # keys even when told to. DumperX works fine and is much faster. Author of # Dumper has been notified. $DNA = DumperX( $Donor ); # The data structure in $Donor has been stringified into $DNA. $Length = length($DNA); open(TO, "> $File"); $Offset = 0; while ($Length) { # Handle partial writes. $Written = syswrite TO, $DNA, $Length, $Offset; (! defined $Written ) and die "System write error: $!\n"; $Length -= $Written; $Offset += $Written; } close(TO); return $RefType; } # ------------------------------ # RestoreStructure -- subroutine STRICT # ------------------------------ # Author: rhardy@webcon.net # # This function will read a specified file containing a captured structure, # restore it to a specified structure of the same type and return whether is # succeeded or not. This function works with almost any complex data # structure (including multi-dimensional hashes). # Function returns the data type on success for easy error detection: # i.e. &RestoreStructure or die; # Syntax: &RestoreStructure($rComplexDataStructure, $FileToRead); sub RestoreStructure { my $Clone = shift; my $File = shift; my ( $DNA ); local $_; # Must read in the file open(FROM, "< $File") or die "Error reading File $File: $!\n"; $DNA=; close(FROM); # Find out what we are restoring and then use $DNA to clone original structure $_=ref($Clone); if ($_ eq "HASH") { %{$Clone} = %{eval $DNA}; $@ and die("RestoreStructure Eval ERROR:$@\n"); return $_; } if ($_ eq "ARRAY") { @{$Clone} = @{eval $DNA}; $@ and die("RestoreStructure Eval ERROR:$@\n"); return $_; } if ($_ eq "SCALAR") { ${$Clone} = ${eval $DNA}; $@ and die("RestoreStructure Eval ERROR:$@\n"); return $_; } (not ref $Clone) and die("Error: Undefined Reference!\n"); # Unrecognized data we simply return an error. CODE and GLOB fall here for now. return 0; } # Usage Example: # In a subroutine which builds you a multidimesional hash: # skip generating the hash from scratch if it exists # on disk from a previous session. if ( -f "$DataFile" ) { $RefType=RestoreStructure(\%::WordsLength, "$DataFile") or die"ERROR: can't retrieve WordsLength!\n"; print "Using $DataFile; Delete to rebuild WordsLength $RefType\.\n"; return 0; } # Save a copy of this WordsLength for later use $RefType=CaptureStructure(\%::WordsLength, "$DataFile"); ($@) and (die "Error writing to file: $@");