+# sender_address_domain,shown_message_size
+sub msg_sort {
+ my $msgs = shift;
+ my $vars = shift;
+ my $reverse = shift;
+
+ my @pieces = ();
+ foreach my $v (@G::sort) {
+ push(@pieces, "\$a->{vars}{\"$v\"} $G::sort_type{$v} \$b->{vars}{\"$v\"}");
+ }
+ my $sort_str = join(" || ", @pieces);
+
+ @$msgs = sort { eval $sort_str } (@$msgs);
+ @$msgs = reverse(@$msgs) if ($reverse);
+}
+
+sub try_load {
+ my $mod = shift;
+
+ eval("use $mod");
+ return $@ ? 0 : 1;
+}
+
+# FREEZE FILE FORMAT:
+# message_data_bytes
+# message_data
+# <...>
+# EOM
+# message_list
+# message_list_bytes <- 10 bytes, zero-packed, plus \n
+
+sub freeze_start {
+ eval("use Storable");
+ die "Storable module not found: $@\n" if ($@);
+ open(O, ">$G::freeze") || die "Can't open freeze file $G::freeze: $!\n";
+ $G::freeze_handle = \*O;
+}
+
+sub freeze_end {
+ close($G::freeze_handle);
+}
+
+sub thaw_start {
+ eval("use Storable");
+ die "Storable module not found: $@\n" if ($@);
+ open(I, "<$G::thaw") || die "Can't open freeze file $G::thaw: $!\n";
+ $G::freeze_handle = \*I;
+}
+
+sub thaw_end {
+ close($G::freeze_handle);
+}
+
+sub freeze_data {
+ my $h = Storable::freeze($_[0]);
+ print $G::freeze_handle length($h)+1, "\n$h\n";
+}
+
+sub freeze_message_list {
+ my $h = Storable::freeze($_[0]);
+ my $l = length($h) + 1;
+ printf $G::freeze_handle "EOM\n$l\n$h\n%010d\n", $l+11+length($l)+1;
+}
+
+sub thaw_message_list {
+ my $orig_pos = tell($G::freeze_handle);
+ seek($G::freeze_handle, -11, 2);
+ chomp(my $bytes = <$G::freeze_handle>);
+ seek($G::freeze_handle, $bytes * -1, 2);
+ my $obj = thaw_data();
+ seek($G::freeze_handle, 0, $orig_pos);
+ return($obj);
+}
+
+sub thaw_data {
+ my $obj;
+ chomp(my $bytes = <$G::freeze_handle>);
+ return(undef) if (!$bytes || $bytes eq 'EOM');
+ my $read = read(I, $obj, $bytes);
+ die "Format error in thaw file (expected $bytes bytes, got $read)\n"
+ if ($bytes != $read);
+ chomp($obj);
+ return(Storable::thaw($obj));
+}
+