Index: ossp-pkg/string-divert/ChangeLog RCS File: /v/ossp/cvs/ossp-pkg/string-divert/ChangeLog,v rcsdiff -q -kk '-r1.9' '-r1.10' -u '/v/ossp/cvs/ossp-pkg/string-divert/ChangeLog,v' 2>/dev/null --- ChangeLog 2005/11/16 10:54:17 1.9 +++ ChangeLog 2005/11/16 12:08:49 1.10 @@ -2,6 +2,15 @@ ChangeLog ========= + 0.96 (16-Nov-2005) + o add folding loop detection to "string" method + o use anonymous names already in "new" method + o don't follow diversions on "folding" method to + allow one to divert back to upper objects, too. + o document that "folding" method returns all + foldings if no name or object is specified. + o change sample2.pl to show the usual "head" diversion + once one is already diverted in "body". 0.95 (16-Nov-2005) o document "bool" method in Divert.pod, too. o allow objects to be passed to "append" and "assign" methods Index: ossp-pkg/string-divert/Divert.pm RCS File: /v/ossp/cvs/ossp-pkg/string-divert/Divert.pm,v rcsdiff -q -kk '-r1.13' '-r1.14' -u '/v/ossp/cvs/ossp-pkg/string-divert/Divert.pm,v' 2>/dev/null --- Divert.pm 2005/11/16 10:55:02 1.13 +++ Divert.pm 2005/11/16 12:08:49 1.14 @@ -43,6 +43,12 @@ our @EXPORT = qw(); our @EXPORT_OK = qw(); +# internal: create an anonymous object name +my $_anonymous_count = 1; +sub _anonymous_name () { + return sprintf("ANONYMOUS:%d", $_anonymous_count++); +} + # object construction sub new ($;$) { my ($proto, $name) = @_; @@ -51,7 +57,7 @@ my $self = {}; bless ($self, $class); - $name ||= ""; + $name ||= &String::Divert::_anonymous_name(); $self->{name} = $name; # name of object $self->{overwrite} = 'none'; # overwrite mode (none|once|always) @@ -228,9 +234,22 @@ my ($self) = @_; return $self->{diversion}->[-1]->string() if (@{$self->{diversion}} > 0); + return $self->_string([]); +} + +# internal: string() operation with loop detection +sub _string ($$) { + my ($self, $visit) = @_; my $string = ''; + if (grep { &String::Divert::_isobjeq($_, $self) } @{$visit}) { + croak "folding loop detected: " . + join(" -> ", map { $_->name() } @{$visit}) . + " -> " . $self->name(); + } + push(@{$visit}, $self); foreach my $chunk (@{$self->{chunks}}) { if (ref($chunk)) { + # folding loop detection my $prefix = ''; # check for existing prefix # (keep in mind that m|([^\n]+)$|s _DOES NOT_ @@ -240,7 +259,7 @@ $prefix = $1; $prefix =~ s|[^ \t]| |sg; } - my $block = $chunk->string(); # recursion! + my $block = $chunk->_string($visit); # recursion! $block =~ s|\n(?=.)|\n$prefix|sg if ($prefix ne ''); $string .= $block; } @@ -248,6 +267,7 @@ $string .= $chunk; } } + pop(@{$visit}); return $string; } @@ -269,12 +289,6 @@ return 0; } -# internal: create an anonymous object name -my $_anonymous_count = 1; -sub _anonymous_name () { - return sprintf("ANONYMOUS:%d", $_anonymous_count++); -} - # operation: append folding sub-object sub fold ($;$) { my ($self, $id) = @_; @@ -333,8 +347,6 @@ # operation: lookup particular or all folding sub-object(s) sub folding ($;$) { my ($self, $id) = @_; - return $self->{diversion}->[-1]->folding($id) - if (@{$self->{diversion}} > 0); if (defined($id)) { my $folding; $folding = undef; foreach my $chunk (@{$self->{chunks}}) { Index: ossp-pkg/string-divert/Divert.pod RCS File: /v/ossp/cvs/ossp-pkg/string-divert/Divert.pod,v rcsdiff -q -kk '-r1.7' '-r1.8' -u '/v/ossp/cvs/ossp-pkg/string-divert/Divert.pod,v' 2>/dev/null --- Divert.pod 2005/11/16 10:54:17 1.7 +++ Divert.pod 2005/11/16 12:08:49 1.8 @@ -263,10 +263,13 @@ =item SAPI: C<$y = $x-E>BC<($name);> +=item SAPI: C<@y = $x-E>BC<();> + =item XAPI: C<$y = ($x EE= $name);> I. This lookups in string object C<$x> the -contained folding sub-object with name C<$name>. +contained folding sub-object with name C<$name>. If C<$name> is not +specified, it returns a list of all folding sub-objects. =item SAPI: C<$x-E>BC<($format, $regex);> @@ -359,14 +362,9 @@ " " . $html->folder("body") . " \n" . "\n"; - - # generate header - $html >> "head"; - $html .= "foo\n"; - $html << 1; + $html >> "body"; # generate body - $html >> "body"; $html .= "\n" . " \n" . " \n" . "
\n" . @@ -378,15 +376,22 @@ "
\n"; + # generate header + $html >> "head"; + $html .= "foo\n"; + $html << 1; + # generate left contents $html >> "left"; $html .= "bar1\n" . "bar2\n"; + $html << 1; # generate right contents $html >> "right"; $html .= "quux1\n" . "quux2\n"; + $html << 1; # undivert all diversions and output unfolded HTML $html << 0; Index: ossp-pkg/string-divert/TODO RCS File: /v/ossp/cvs/ossp-pkg/string-divert/TODO,v rcsdiff -q -kk '-r1.2' '-r1.3' -u '/v/ossp/cvs/ossp-pkg/string-divert/TODO,v' 2>/dev/null --- TODO 2003/05/23 11:09:57 1.2 +++ TODO 2005/11/16 12:08:49 1.3 @@ -2,8 +2,6 @@ TODO ==== - o check recursion on folding and diversion to avoid loops - o resurrect TIE mechanism for assignment operator once Perl is no longer buggy (see "BUGS" in "perldoc overload") and no longer looses the overloading after STORE. Index: ossp-pkg/string-divert/sample2.pl RCS File: /v/ossp/cvs/ossp-pkg/string-divert/sample2.pl,v rcsdiff -q -kk '-r1.2' '-r1.3' -u '/v/ossp/cvs/ossp-pkg/string-divert/sample2.pl,v' 2>/dev/null --- sample2.pl 2003/05/23 11:09:57 1.2 +++ sample2.pl 2005/11/16 12:08:49 1.3 @@ -16,14 +16,9 @@ " " . $html->folder("body") . " \n" . "\n"; - -# generate header -$html >> "head"; -$html .= "foo\n"; -$html << 1; +$html >> "body"; # generate body -$html >> "body"; $html .= "\n" . " \n" . " \n" . "
\n" . @@ -35,6 +30,11 @@ "
\n"; +# generate header +$html >> "head"; +$html .= "foo\n"; +$html << 1; + # generate left contents $html >> "left"; $html .= "bar1\n" . @@ -45,6 +45,7 @@ $html >> "right"; $html .= "quux1\n" . "quux2\n"; +$html << 1; # undivert all diversions and output unfolded HTML $html << 0; Index: ossp-pkg/string-divert/test.pl RCS File: /v/ossp/cvs/ossp-pkg/string-divert/test.pl,v rcsdiff -q -kk '-r1.6' '-r1.7' -u '/v/ossp/cvs/ossp-pkg/string-divert/test.pl,v' 2>/dev/null --- test.pl 2005/02/22 13:21:34 1.6 +++ test.pl 2005/11/16 12:08:49 1.7 @@ -23,7 +23,7 @@ ## use 5.006; -use Test::More tests => 38; +use Test::More tests => 37; # test: module loading BEGIN { use_ok('String::Divert') }; @@ -34,7 +34,6 @@ $x->destroy; $x = new String::Divert; ok(defined($x), "object (re)creation"); -ok($x->name() eq "", "object name"); $x->name("xx"); ok($x->name() eq "xx", "overwritten object name"); $x->name("x");