new version of ip address storage
[spider.git] / perl / DXUtil.pm
index 9c14715c5ee073bdfa105302bc36c0bfaf5f6cd9..baa041d42bce04d1c232d2e4edf7cfb79ec2e8d0 100644 (file)
@@ -13,7 +13,7 @@ use Date::Parse;
 use IO::File;
 use File::Copy;
 use Data::Dumper;
-
+use Time::HiRes qw(gettimeofday tv_interval);
 
 use strict;
 
@@ -27,6 +27,7 @@ require Exporter;
              print_all_fields cltounix unpad is_callsign is_latlong
                         is_qra is_freq is_digits is_pctext is_pcflag insertitem deleteitem
                         is_prefix dd is_ipaddr $pi $d2r $r2d localdata localdata_mv
+                        diffms _diffms ahour piplist mindate adate
             );
 
 
@@ -53,6 +54,24 @@ sub atime
        return $buf;
 }
 
+# just the hour
+sub ahour
+{
+       my $t = shift;
+       my ($sec,$min,$hour,$mday,$mon,$year) = gmtime((defined $t) ? $t : time);
+       my $buf = sprintf "%02d:%02d:%02d", $hour, $min, $sec;
+       return $buf;
+}
+
+sub adate
+{
+       my $t = shift;
+       my ($sec,$min,$hour,$mday,$mon,$year) = gmtime((defined $t) ? $t : time);
+       $year += 1900;
+       my $buf = sprintf "%02d%s%04d", $mday, $month[$mon], $year;
+       return $buf;
+}
+
 # get a zulu time in cluster format (2300Z)
 sub ztime
 {
@@ -192,7 +211,7 @@ sub ptimelist
 sub parray
 {
        my $ref = shift;
-       return ref $ref ? join(', ', @{$ref}) : $ref;
+       return ref $ref ? join(',', @{$ref}) : $ref;
 }
 
 # take the arg as an array reference and print as a list of pairs
@@ -219,13 +238,58 @@ sub phash
        my $out;
 
        while (my ($k,$v) = each %$ref) {
-               $out .= "${k}=>$v, ";
+               if (ref $v eq 'ARRAY') {
+                       $out = "${k}=>[" . parray($v) . "],";
+               } elsif (ref $v eq 'HASH') {
+                       $out = "${k}=>{" . phash($v) . "},";
+               } else {
+                       $out .= "${k}=>$v,";
+               }
        }
-       chop $out;                                      # remove last space
        chop $out;                                      # remove last comma
        return $out;
 }
 
+sub mindate
+{
+       my $t = shift;
+       my $out;
+
+       if ($main::system-$t < 86400 ) {
+               $out = ahour($t);
+       } elsif ($main::system-$t < 365*86400) {
+               $out = adate($t);
+               chop $out for (1..4);
+               $out .= ' ' . atime($t);
+               chop $out for (1..3);
+       } else {
+               $out = atime($t);
+               $out =~ s/\@/ /;
+       }
+       return $out;
+}
+
+# like phash but prints dates and times
+sub piplist
+{
+       my $ref = shift;
+       my $out;
+
+       return $ref unless ref $ref;
+       
+       while (my ($k,$v) = each %$ref) {
+               if (ref $v eq 'HASH') {
+                       $out .= piplist($v);
+               } elsif (ref $v eq 'ARRAY') {
+                       $out .= join(',', map { sprintf "$_->[0]@%s", mindate($_->[1]) }  ref $v->[0] eq 'ARRAY' ? @$v : $v);
+               } else {
+                       $out .= $v;
+               }
+       }
+       $out =~ s/,+$//;                                        # remove last comma
+       return $out;
+}
+
 sub _sort_fields
 {
        my $ref = shift;
@@ -382,11 +446,11 @@ sub unpad
 sub is_callsign
 {
        return $_[0] =~ m!^
-                                         (?:(?:[A-Z]{1,2}\d* | \d[A-Z]{1,2}\d*)/)?   # out of area prefix /
-                                         (?:[A-Z]{1,2}\d+ | \d[A-Z]{1,2}\d+)?        # main prefix one 
-                                         [A-Z]{1,5}                                  # callsign letters
-                                         (?:-\d{1,2})?                               # - nn possibly (eg G8BPQ-8)
-                                         (?:/[0-9A-Z]{1,7})?                        # / another prefix, callsign or special label (including /MM, /P as well as /EURO or /LGT) possibly
+                                         (?:\d?[A-Z]{1,2}\d*/)?    # out of area prefix /  
+                                         (?:\d?[A-Z]{1,2}\d+)      # main prefix one (required) 
+                                         [A-Z]{1,5}                # callsign letters (required)
+                                         (?:-(?:\d{1,2}|\#))?      # - nn possibly (eg G8BPQ-8) or -# (an RBN spot) 
+                                         (?:/[0-9A-Z]{1,7})?       # / another prefix, callsign or special label (including /MM, /P as well as /EURO or /LGT) possibly
                                          $!x;
 
        # longest callign allowed is 1X11/1Y11XXXXX-11/XXXXXXX
@@ -427,7 +491,8 @@ sub is_digits
 # does it look like a qra locator?
 sub is_qra
 {
-       return $_[0] =~ /^[A-Ra-r][A-Ra-r]\d\d[A-Xa-x][A-Xa-x]$/;
+       return unless length $_[0] == 4 || length $_[0] == 6;
+       return $_[0] =~ /^[A-Ra-r][A-Ra-r]\d\d(?:[A-Xa-x][A-Xa-x])?$/;
 }
 
 # does it look like a valid lat/long
@@ -439,7 +504,7 @@ sub is_latlong
 # is it an ip address?
 sub is_ipaddr
 {
-    return $_[0] =~ /^\d+\.\d+\.\d+\.\d+$/ || $_[0] =~ /^[0-9a-f:]+$/;
+    return $_[0] =~ /^\d+\.\d+\.\d+\.\d+$/ || $_[0] =~ /^[0-9a-f:,]+$/;
 }
 
 # insert an item into a list if it isn't already there returns 1 if there 0 if not
@@ -470,15 +535,15 @@ sub deleteitem
 sub localdata
 {
        my $ifn = shift;
-       my $ofn = "$main::data/$ifn";
+       my $ofn = "$main::local_data/$ifn";
        my $tfn;
        
        if (-e "$main::local_data") {
-               $tfn = "$main::local_data/$ifn";
-               if (-e $tfn && -e $ofn) {
-                       $ofn = $tfn if -M $tfn < -M $ofn;
-               } elsif (-e $tfn) {
-                       $ofn = $tfn;
+               $tfn = "$main::data/$ifn";
+               if ((-e $tfn) && (-e $ofn)) {
+                       $ofn = $tfn if -M $ofn < -M $tfn;
+               } else {
+                       $ofn = $tfn if -e $tfn;
                }
        }
 
@@ -496,3 +561,27 @@ sub localdata_mv
        }
 }
 
+# measure the time taken for something to happen; use Time::HiRes qw(gettimeofday tv_interval);
+sub _diffms
+{
+       my $ta = shift;
+       my $tb = shift || [gettimeofday];
+       my $a = int($ta->[0] * 1000) + int($ta->[1] / 1000); 
+       my $b = int($tb->[0] * 1000) + int($tb->[1] / 1000);
+       return $b - $a;
+}
+
+sub diffms
+{
+       my $call = shift;
+       my $line = shift;
+       my $ta = shift;
+       my $no = shift;
+       my $tb = shift;
+       my $msecs = _diffms($ta, $tb);
+
+       $line =~ s|\s+$||;
+       my $s = "subprocess stats cmd: '$line' $call ${msecs}mS";
+       $s .= " $no lines" if $no;
+       DXDebug::dbg($s);
+}