}, $_[0];
}
-sub rootset { @{$_[0]{rootset}} }
-
sub thread {
my $self = shift;
- $self->_setup();
+ _add_message($self, $_) foreach @{$self->{messages}};
$self->{rootset} = [
grep { !$_->{parent} } values %{$self->{id_table}} ];
- $self->_finish();
-}
-
-sub _finish {
- my $self = shift;
delete $self->{id_table};
- delete $self->{seen};
}
sub _get_cont_for_id ($$) {
$self->{id_table}{$mid} ||= PublicInbox::SearchThread::Msg->new($mid);
}
-sub _setup {
- my ($self) = @_;
-
- _add_message($self, $_) foreach @{$self->{messages}};
-}
-
sub _add_message ($$) {
my ($self, $smsg) = @_;
}
sub order {
- my $self = shift;
- my $ordersub = shift;
+ my ($self, $ordersub) = @_;
# make a fake root
my $root = _get_cont_for_id($self, 'fakeroot');
} while ($walk);
}
-sub order_children {
- my $self = shift;
- my $ordersub = shift;
-
- return unless $ordersub;
-
- my $sub = sub {
- my $cont = shift;
- my $children = $cont->children;
- return if @$children < 2;
- $cont->set_children( $ordersub->( $children ) );
- };
- $self->iterate_down( undef, $sub );
- undef $sub;
-}
-
# non-recursive version of recurse_down to avoid stack depth warnings
sub recurse_down {
my ($self, $callback) = @_;
my %seen;
my @q = ($self);
while (my $cont = shift @q) {
- $seen{$cont}++;
+ $seen{$cont} = 1;
$callback->($cont);
if (my $next = $cont->{next}) {
}
}
-sub iterate_down {
- my $self = shift;
- my ($before, $after) = @_;
+sub order_children {
+ my ($walk, $ordersub) = @_;
my %seen;
- my $walk = $self;
- my $depth = 0;
my @visited;
while ($walk) {
- push @visited, [ $walk, $depth ];
- $before->($walk, $depth) if $before;
+ push @visited, $walk;
# spot/break loops
- $seen{$walk}++;
+ $seen{$walk} = 1;
my $child = $walk->{child};
if ($child && $seen{$child}) {
}
# go down, or across
- if ($child) {
- $next = $child;
- ++$depth;
- }
+ $next = $child if $child;
# no next? look up
if (!$next) {
my $up = $walk;
while ($up && !$next) {
$up = $up->{parent};
- --$depth;
$next = $up->{next} if $up;
}
}
$walk = $next;
}
- return unless $after;
- while (@visited) { $after->(@{ pop @visited }) }
+ foreach my $cont (@visited) {
+ my $children = $cont->children;
+ next if @$children < 2;
+ $children = $ordersub->($children);
+ $cont = $cont->{child} = shift @$children;
+ do {
+ $cont = $cont->{next} = shift @$children;
+ } while ($cont);
+ }
}
1;