#!/usr/bin/perl -w package Tie::Hash::Stack; ###################### # # Tie::Hash::Stack; # v0.03 # Michael K. Neylon # mneylon-pm@masemware.com # June 21, 2001 # # Creates and maintains a 'stacked' hash, see documentation # for more details # # Suggestions/Comments/Ideas are highly desired and can be # sent to the eamil address above. # # Change History: # # v0.03 - June 21, 2001 # - Added merge_hash, shift_hash, and unshift_hash functions # - Added optional values for TIEHASH, push_hash, and unshift_hash # - Improved croak messages # - Added minor protection for pop_hash'ing or shift'ing too far # (array is resetted to a blank holding in this case.) # # v0.02 - June 20, 2001 # - Cleaned up CLEAR function # - Used shift and unshift instead of pop and push to make FETCH # work faster # - Adjusted workings of push_/pop_hash # # v0.01 - June 19, 2001 # - Initial Release # ###################### use strict; use Carp; BEGIN { use Exporter (); use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS); $VERSION = 0.02; @ISA = qw(Exporter); @EXPORT = qw(push_hash pop_hash); %EXPORT_TAGS = ( ); @EXPORT_OK = qw(); } use vars @EXPORT_OK; sub TIEHASH { my $self = shift; my $newhash = shift || {}; croak "Argument must be a hashref in Tie::Hash::Stack constructor" unless UNIVERSAL::isa( $newhash, 'HASH' ); my $hash_array = [ $newhash ]; # Create array, with one bl +ank hash return bless $hash_array, $self; } sub FETCH { my $self = shift; my $key = shift; foreach ( @$self ) { # $_ is a hashref! return $_->{ $key } if ( exists $_->{ $key } ); } return undef; } sub STORE { my $self = shift; my $key = shift; my $value = shift; $self->[0]->{ $key } = $value; } sub DELETE { my $self = shift; my $key = shift; my $return = $self->FETCH( $key ); foreach ( @$self ) { delete $_->{ $key } if ( exists $_->{ $key } ); } return $return; } sub CLEAR { my $self = shift; @$self = ( { } ); } sub EXISTS { my $self = shift; my $key = shift; foreach ( @$self ) { return 1 if exists $_->{ $key }; } return undef; } sub FIRSTKEY { my $self = shift; my %hash; foreach ( @$self ) { foreach my $key ( keys %$_ ) { $hash{ $key } = 1; } } my @keys = sort keys %hash; return $keys[ 0 ]; } sub NEXTKEY { my $self = shift; my $lastkey = shift; my %hash; foreach ( @$self ) { foreach my $key ( keys %$_ ) { $hash{ $key } = 1; } } my @keys = sort keys %hash; my $i = 0; $i++ while ( ( $lastkey ne $keys[ $i ] ) && ( $i < @keys - 1 ) ) ; if ( $i == @keys - 1 ) { return (); } else { return $keys[ $i+1 ]; } } sub DESTROY { } sub merge_hash (\%) { my $href = shift; my $obj = tied %$href; croak "must be a Tie::Hash::Stack tied hash" unless $obj and $obj->isa('Tie::Hash::Stack'); my %hash; foreach ( @$obj ) { foreach my $key ( keys %$_ ) { $hash{ $key } = $_{ $key }; } } return %hash; } sub push_hash (\%;\%) { my $href = shift; my $obj = tied %$href; my $addhash = shift || {}; croak "First argument must be a Tie::Hash::Stack tied hash in push +_hash" unless $obj and $obj->isa('Tie::Hash::Stack'); croak "Second argument must be a hashref in push_hash" unless UNIVERSAL::isa( $addhash, 'HASH' ); unshift @$obj, $addhash; } sub pop_hash (\%) { my $href = shift; my $obj = tied %$href; croak "First argument must be a Tie::Hash::Stack tied hash in pop_ +hash" unless $obj and $obj->isa('Tie::Hash::Stack'); shift @$obj; @$obj = ( { } ) if !@$obj; } sub unshift_hash (\%;\%) { my $href = shift; my $obj = tied %$href; my $addhash = shift || {}; croak "First argument must be a Tie::Hash::Stack tied hash in unsh +ift_hash" unless $obj and $obj->isa('Tie::Hash::Stack'); croak "Second argument must be a hashref in unshift_hash" unless UNIVERSAL::isa( $addhash, 'HASH' ); push @$obj, $addhash; } sub shift_hash (\%) { my $href = shift; my $obj = tied %$href; croak "First argument must be a Tie::Hash::Stack tied hash in shif +t_hash" unless $obj and $obj->isa('Tie::Hash::Stack'); pop @$obj; @$obj = ( { } ) if !@$obj; } =head1 NAME Tie::Stack::Hash; =head1 SYNOPSIS use Tie::Hash::Stack qw(pop_hash push_hash); my %hash; tie( %hash, "Tie::Hash::Stack" ); # Ties the hash $hash{ 1 } = "one"; $hash{ 2 } = "two"; $hash{ 3 } = "three"; push_hash %hash; # Pushes a new hash on the stack $hash{ 2 } = "II"; # $hash{ 2 } now 'II' $hash{ 4 } = "IV"; push_hash %hash; $hash{ 3 } = "9/3"; # $hash{ 3 } now '9/3' $hash{ 5 } = "10/2"; pop_hash %hash; # $hash{ 3 } now 'three'; delete $hash{ 2 }; # $hash{ 2 } now undef'ed; my %merged = merge_hash %hash; # ( 1=>one, 3=>three, 4=>IV ) =head1 DESCRIPTION C<Tie::Hash::Stack> allows one to tie a hash to a data structure that is composed of an ordered (FILO) sequence of hashes; hash values are always set on the newest hash of the stack, and are retrieved from the hash that contains the requested that is newest on the stack. The stack can be manipulated to add or remove these hashes. This type of structure is good when on is collecting data in stages with the possibility of having to "back up" to previous stages. In cases where the same key is in two or more hashes on the stack, + the value from the most recent hash containing that key will be returned. When C<tie>'d, the new hash will already have one hash on the stack, so that it can be used without any extra code. Optionally, a hash reference may be passed which will be used as the initial hash within the array. Besides the standard hash functions, there are two functions that can be accessed through the tie'd hash variable. C<push_hash> - Pushes an empty hash onto the hash; any further hash assignments will be placed into this hash until it is removed +, or a new hash pushed onto the stack. A optional second argument may be a reference to a hash which will be pushed onto the stack instead of an empty one. C<pop_hash> - Removes the last hash on the stack after deleting th +e values from it. If all hashes are removed, the stack is reset wit +h an empty hash. C<shift_hash>, C<unshift_hash> - Complimentary functions of C<pop_hash> and C<push_hash>; removes the hash at the front of the + stack, or adds a new hash to the front of the stack. C<unshift_ha +sh> also takes a similar optional second arguement as with C<push_hash +>. C<merge_hash> - Merges all the hashes into one and returns this new (untied) hash; duplicated keys are treated as described above. =head1 HISTORY Revision 0.03 2001/06/21 Michael K. Neylon Added merge_hash, shift_hash, and unshift_hash functions Added optional values for TIEHASH, push_hash, and unshift_hash Improved croak messages Added minor protection for pop_hash'ing or shift'ing too far (array is resetted to a blank holding in this case.) Revision 0.02 2001/06/20 Michael K. Neylon Cleaned up CLEAR function Used shift/unshift instead of pop/push to improve FETCH speed Converted push_hash and pop_hash to exported functions. (Thanks to Jeff 'japhy' Pinyan) Revision 0.01 2001/06/19 Michael K. Neylon Initial revision =head1 AUTHOR This package was written by Michael K. Neylon =head1 COPYRIGHT Copyright 2001 by Michael K. Neylon =head1 LICENSE Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the "Softwar +e"), to deal in the Software without restriction, including without limitat +ion the rights to use, copy, modify, merge, publish, distribute, sublicens +e, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be include +d in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRES +S OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILIT +Y, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHAL +L THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. =cut 1;

In reply to Tie::Hash::Stack by Masem

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.