6 use DBI qw(looks_like_number);
13 'json!' => \my $opt_json,
14 'db=s' => \my $opt_db,
15 'verbose|v!' => \my $opt_verbose,
16 'debug|d!' => \my $opt_debug,
19 my $j = JSON::XS->new->ascii->pretty(0);
21 my $dbh = DBI->connect("dbi:SQLite:dbname=$opt_db","","", {
22 RaiseError => 1, PrintError => 0, AutoCommit => 0
24 $dbh->do("PRAGMA synchronous = OFF");
25 $dbh->do("DROP TABLE IF EXISTS node");
28 id integer primary key,
36 kids_node_count integer,
42 my $node_ins_sth = $dbh->prepare(q{
43 INSERT INTO node VALUES (?,?,?,?,?, ?,?,?,?,?,?)
52 print " " x $x->{depth};
53 print qq({ "id": "$x->{id}", "name": "$x->{name}", "depth":$x->{depth}, "children":[ \n);
60 delete $seqn2node{$x->{id}};
61 my $self_size = 0; $self_size += $_ for values %{$x->{leaves}};
62 $x->{self_size} = $self_size;
63 if (my $parent = $stack[-1]) {
65 $x->{parent_id} = $parent->{id};
66 # accumulate into parent
67 $parent->{kids_node_count} += 1 + ($x->{kids_node_count}||0);
68 $parent->{kids_size} += $self_size + $x->{kids_size};
69 push @{$parent->{child_id}}, $x->{id};
74 print " " x $x->{depth};
75 my $size = $self_size + $x->{kids_size};
76 print qq(], "data":{ "\$area": $size } },\n);
79 my $attr_json = $j->encode($x->{attr});
80 my $leaves_json = $j->encode($x->{leaves});
81 $node_ins_sth->execute(
82 $x->{id}, $x->{name}, $x->{title}, $x->{depth}, $x->{parent_id},
83 $x->{self_size}, $x->{kids_size}, $x->{kids_node_count},
84 $x->{child_id} ? join(",", @{$x->{child_id}}) : undef,
85 $attr_json, $leaves_json,
92 print "memnodes = [" if $opt_json;
96 my ($type, $id, $val, $name, $extra) = split / /, $_, 5;
97 if ($type eq "N") { # Node ($val is depth)
98 while ($val < @stack) {
99 leave_node(my $x = pop @stack);
100 warn "N $id d$val ends $x->{id} d$x->{depth}: size $x->{self_size}+$x->{kids_size}\n"
103 die 1 if $stack[$val];
104 my $node = $stack[$val] = { id => $id, name => $name, extra => $extra, attr => {}, leaves => {}, depth => $val, self_size=>0, kids_size=>0 };
106 $seqn2node{$id} = $node;
108 elsif ($type eq "L") { # Leaf name and memory size
109 my $node = $seqn2node{$id} || die;
110 $node->{leaves}{$name} += $val;
112 elsif (looks_like_number($type)) { # Attribute type, name and value
113 my $node = $seqn2node{$id} || die;
114 my $attr = $node->{attr} || die;
115 if ($type == 1) { # NPattr_NAME
116 warn "Node $id already has attribute $type:$name (value $attr->{$type}{$name})\n"
117 if exists $attr->{$type}{$name};
118 $attr->{$type}{$name} = $val || $id;
119 warn "A \@$id: '$name' $val\n";
120 $node->{title} = $name if $type == 1 and !$val;
122 elsif (2 <= $type and $type <= 4) { # NPattr_PAD*
123 warn "Node $id already has attribute $type:$name (value $attr->{$type}[$val])\n"
124 if defined $attr->{$type}[$val];
125 $attr->{$type}[$val] = $name;
128 warn "Invalid attribute type '$type' on line $. ($_)";
132 warn "Invalid type '$type' on line $. ($_)";
135 $dbh->commit if $dbh and $id % 10_000 == 0;
140 leave_node($x = pop @stack) while @stack;
141 warn "EOF ends $x->{id} d$x->{depth}: size $x->{self_size}+$x->{kids_size}\n";
143 print " ];\n" if $opt_json;
145 $dbh->commit if $dbh;
149 warn Dumper(\%seqn2node);
152 SV(PVAV) fill=1/1 [#1 @0]
159 : : : : SV(PVAV) fill=-1/-1 [#5 @4]
160 : : : : : +64 sv =168
167 N 1 0 SV(PVAV) fill=1/1
174 N 5 4 SV(PVAV) fill=-1/-1