in reply to Re^2: patchable settings (big readmores)
in thread patchable settings

Played with it a little, mostly reindenting; removed the eval checks: we aren't preserving blessed refs, so no point in even allowing them. Put the hash check first in packVars. Don't need to escape = for arrays (unless I'm missing something).(Update: added back =). Started to mess with cmpVars but ran out of time. My inclination would be just to treat too high version numbers as if they were the current rather than return an error. All the error conditions should get logged rather than die or return.
sub packVars { my $varsref = $_[0]; my $seenref = $_[1]; return unless $varsref; return if $seenref->{0+$varsref}++; if (ref $varsref eq "HASH") { return join "&", "$PackVer:H", map { my $v = $varsref->{$_}; $v = ref $v ? packVars( $v, $seenref ) : defined($v) ? $v : ' '; join '=', map { s/([%&=])/ sprintf '%%%02x', ord($1) /ge; $_ +} $_, $v; } sort keys %$varsref; } elsif (ref $varsref eq "ARRAY") { return join "^", "$PackVer:A", map { my $v = ref $_ ? packVars( $_, $seenref ) : defined($_) ? $_ : ''; $v =~ s/([~^=])/sprintf '~%02x', ord($1)/ge; $v; } @$varsref; } else { die "Can't handle vars of type ".ref($varsref)."\n"; } } sub unpackVars { my $vars_str = $_[0]; return {} unless $vars_str; # version 00: original format # version 01: keys are escaped, not just values, handles nested re +fs. my $vars; #print "$vars_str\n"; $vars_str =~ s/^(==\d\d):([AH])(.)//; my ($format_version,$type,$split)=($1,$2,$3); #print "$format_version : $type : $split\n"; unless (defined $format_version) { # No format/format version "00" my %vars = map split(/=/, $_, 2), split /&/, $vars_str; unescape( values %vars ); $vars{$_} eq ' ' and $vars{$_} = '' for keys %vars; return \%vars; } elsif ($format_version le $PackVer) { if ($type eq 'H') { for (split /\Q$split\E/, $vars_str) { s/%(\w\w)/ chr(hex($1)) /ge for my ($k,$v) = split /=/, +$_, -1; # special data to unpack? if ($v=~/^==\d\d:[AH]/) { # nested value $v = unpackVars($v); } $vars->{$k} = $v; } } elsif ($type eq 'A') { for (split /\Q$split\E/, $vars_str) { s/~(\w\w)/ chr(hex($1)) /ge; # special data to unpack? if (/^==\d\d:[AH]/) { # nested value $_ = unpackVars($_); } push @{$vars), $_; } } else { return "Unknown type! $type"; } } else { return "Version number too high! ($format_version gt $PackVer)"; } return $vars; } sub cmpVars { my ($var1str, $var2str) = @_; return 0 if $var1str eq $var2str; # upgrade to new version /^$PackVer:[AH]/ or $_ = packVars( unpackVars( $_ ) ) for ($var1str, $var2str); return $var1str cmp $var2str; }

Replies are listed 'Best First'.
Re^4: patchable settings (big readmores)
by demerphq (Chancellor) on Oct 17, 2004 at 17:13 UTC

    Ok, i took yours and ran further. Neither of ours handled strings starting with $PackVer. This does, as well as handling undef properly. It also include enhanced benchmark results from Dumper Prompt here on PM.


    ---
    demerphq

      First they ignore you, then they laugh at you, then they fight you, then you win.
      -- Gandhi

      Flux8