# # Copyright (c) 1995 Fernando Trias. All rights reserved. # This is test software. You are granted permission to use or # modify this software for the purposes of testing. You may # redistribute this software as long as this intent is made # clear. # use Fame::HLI; package Fame::DB; use Carp; use Exporter; use DynaLoader; @ISA = (Exporter, DynaLoader); sub AUTOLOAD { local($constname); $AutoLoader::AUTOLOAD = $AUTOLOAD; goto &AutoLoader::AUTOLOAD; } # # Fame utility library # # FT orig. 7/28/95 # 9/95 # # # EXTERNAL USE VARIBABLES # # default frequency (read/write) $FREQ = &Fame::HLI::HDAILY; # default type $TYPE=&Fame::HLI::HNUMRC; #default basis $BASIS=&Fame::HLI::HBSDAY; #default observed $OBSERVED=&Fame::HLI::HOBSUM; #default class $CLASS=&Fame::HLI::HSERIE; # default wildcard for FIRST and NEXT in the "Tie" routines (r/w) $WILD = "?"; # list of open databases (read only) indexed by the db code # returned by fameopen. $TIEDB{0}=""; # # INTERNAL USE VARIABLES # # list of wildcard databases @WILDDB=(); # # UTILITIES # # # ($year, $per) = &getdate($d, $freq) # # $year year (or 0 for case series) # $per period (or case number) # $d string date (like "1jan95" or "95q1") followed by # an optional +/- offset # $freq optional frequency code (use $FREQ if not specified) # sub getdate { my ($d, $freq, $year, $per)=@_; my ($status, $date); #print STDERR "ydate $d\n"; if (!$d || $d eq "" || $d eq "*") { return($year, $per); } if (!$freq) { $freq=$FREQ; } if ($freq==&Fame::HLI::HCASEX) { $d =~ s/^\d+://; return (0, $d); } if ($d =~ /:/) { ($year, $per)=split(/:/,$d,2); if ($year<100) { $year += 1900; } return ($year, $per); } # extract string ($dd) and +/- offset ($do) my ($dd,$do)=($d =~ /^([^+-]+)([+-]\d+)?/); print STDERR "xdate $d:$dd:$do\n"; &Fame::HLI::cfmldat($status, $freq, $date, $dd, &Fame::HLI::HJAN, &Fame::HLI::HFYFST, 1900); &Fame::HLI::cfmdatp($status, $freq, $date+$do, $year, $per); #print STDERR "xxdate $status $freq: $year, $per\n"; return ($year, $per); } # # &Read # # $db database key # $k string object name # $start start string date # $end end string date # # returns array of values # sub Read { my($db, $k, $start, $end)=@_; my(@i, @x); if (ref($db)) { $db=&famefind($k,@$db); } if ($db==-1) { return undef; } @i=&Fame::HLI::famegetinfo($db,$k); #print STDERR "info2 $db $k ",join(":",@i),"\n"; if ($i[0]==0) { return undef; } ($sy, $sp)=&getdate($start, $i[2], @i[5,6]); ($ey, $ep)=&getdate($end, $i[2], @i[7,8]); #print STDERR "read2 $db $k $i[2]: $sy $sp $ey $ep\n"; if ($sp<0 || $ep<0) { return undef; } if ($i[1] == &Fame::HLI::HSTRNG) { @x=&readstrings($db, $k, $i[2], $sy, $sp, $ey, $ep); } else { @x=&Fame::HLI::fameread($db, $k, $sy, $sp, $ey, $ep); } return @x; } # # &Write # # $db database key # $k string object name # $start start string date # @val array of values to store # sub Write { my($db, $k, $start, @val)=@_; my(@i, @x); if ($#val<0) { return undef; } if (ref($db)) { $db=&famefind($k,@$db); } if ($db==-1) { return undef; } @i=&Fame::HLI::famegetinfo($db,$k); if ($i[0]==0) { return undef; } ($sy, $sp)=&getdate($start, $i[2], @i[5,6]); #print STDERR "Write: $db, $k, $sy, $sp, @val\n"; if ($i[1] == &Fame::HLI::HSTRNG) { &writestrings($db, $k, $i[2], $sy, $sp, @val); } else { &Fame::HLI::famewrite($db, $k, $sy, $sp, @val); } } # # readstrings -- internal # sub readstrings { my($db,$k,$freq,$sy,$sp,$ey,$ep)=@_; my($num, $d, $sdate, $edate, $status, $r1, $r2, $r3, $str, $len); my(@ret)=(); #print STDERR "read3 $db $k: $sy, $sp, $ey, $ep\n"; if ($freq == &Fame::HLI::HCASEX) { for($d=$sp;$d<=$ep;$d++) { $num=-1; &Fame::HLI::cfmsrng($status,$freq,$sy,$d,$sy,$d,$r1,$r2,$r3,$num); &Fame::HLI::cfmrstr($status,$db,$k,$r1,$r2,$r3,$str, &Fame::HLI::HNMVAL,$len); #print STDERR "string $d: $str\n"; push(@ret,$str); } } else { &Fame::HLI::cfmpdat($status, $freq, $sdate, $sy, $sp); &Fame::HLI::cfmpdat($status, $freq, $edate, $ey, $ep); for($d=$sdate; $d <= $edate; $d++) { &Fame::HLI::cfmdatp($status, $freq, $d, $sy, $sp); $num=-1; &Fame::HLI::cfmsrng($status,$freq,$sy,$sp,$sy,$sp,$r1,$r2,$r3,$num); &Fame::HLI::cfmrstr($status,$db,$k,$r1,$r2,$r3,$str, &Fame::HLI::HNMVAL,$len); push(@ret,$str); } } return @ret; } # # writestrings -- internal # sub writestrings { my($db,$k,$freq,$sy,$sp,@val)=@_; my($num, $d, $status, $r1, $r2, $r3, $str, $len); if ($freq == &Fame::HLI::HCASEX) { $d=$sp; foreach $str (@val) { $len = length($str); $d++; $num=-1; &Fame::HLI::cfmsrng($status,$freq,$sy,$d,$sy,$d,$r1,$r2,$r3,$num); &Fame::HLI::cfmwstr($status,$db,$k,$r1,$r2,$r3,$str, &Fame::HLI::HNMVAL,$len); } } else { &Fame::HLI::cfmpdat($status, $freq, $d, $sy, $sp); foreach $str (@val) { $len = length($str); &Fame::HLI::cfmdatp($status, $freq, $d++, $sy, $sp); $num=-1; &Fame::HLI::cfmsrng($status,$freq,$sy,$sp,$sy,$sp,$r1,$r2,$r3,$num); &Fame::HLI::cfmwstr($status,$db,$k,$r1,$r2,$r3,$str, &Fame::HLI::HNMVAL,$len); } } } # # &Create # # $db reference to array of databases to access # or a single database number. Will write # to the first database in the list. # $name object name # the following are optional: # $class class code # $freq frequency code # $type object type # $basis basisi attribute # $observ observed attribute # sub Create { my($db, $name, $class, $freq, $type, $basis, $observ)=@_; my($status, $dbkey); if (ref($db)) { $db=$db->[0]; } $class=$CLASS unless $class; $freq=$FREQ unless $freq; $type=$TYPE unless $type; $basis=$BASIS unless $basis; $observ=$OBSERVED unless $observ; #print STDERR "$status,$db,$name,$class,$freq,$type,$basis,$observ\n"; &Fame::HLI::cfmnwob($status,$db,$name,$class,$freq,$type,$basis,$observ); if ($status==&Fame::HLI::HSUCC) { return 1; } else { $!=$status; return 0; } } # # $db = famefind ($key, @list) # # $db = database were $key resides or -1 for none # $key = key to find # @list = list of open database codes # sub famefind { my($key,@list)=@_; my($db,@i); foreach $db (@list) { #print STDERR "looking $db $key\n"; if (&Fame::HLI::famegettype($db,$key)) { return $db; } } #print STDERR "not found $key\n"; return -1; } sub fameerror { my($status,$module)=@_; return if $status = &Fame::HLI::HSUCC; if ($module) { print STDERR "FAME HLI ERROR $status in $module: ",&getsta($status),"\n"; } else { print STDERR "FAME HLI ERROR $status: ",&getsta($status),"\n"; } } # # Object-oriented stuff # #sub new { #my $self = []; #my $pack = shift; #my (@l)=@_; ## print STDERR "new open $l[0]\n"; #$self->[0] = &Fame::HLI::fameopen(@l); #if ($self->[0] == -1) { return undef; } #bless $self #} sub new { my $self = []; my $pack = shift; &append($self, @_) || return undef; bless $self; } sub append { my $self = shift; my($mode, $db, @dbl); $mode=&Fame::HLI::HRMODE; foreach $db (@_) { #print STDERR "check $db\n"; if ($db =~ /^\d+$/) { $mode=$db; next; } $x=&Fame::HLI::fameopen($db,$mode); #print STDERR "tie $db:$mode:$x\n"; if ($x == -1) { return undef; } push(@$self, $x); } return $self; } sub append_db { my $self = shift; my $db; foreach $db (@_) { push(@$self, $db); } return $self; } sub destroy { my $self = shift; my $v; foreach $v (@$self) { &Fame::HLI::fameclose($v); } } sub error { &fameerror($!); } # # TIE functions # sub TIEHASH { my($obj, @list)=@_; my($x, @db, $db); @db=(); #print STDERR "TIE $obj @list\n"; if (ref($list[0])) { @list=@{$list[0]}; } $mode=&Fame::HLI::HRMODE; foreach $db (@list) { #print STDERR "check $db\n"; if ($db =~ /^\d+$/) { $mode=$db; next; } $x=&Fame::HLI::fameopen($db,$mode); #print STDERR "tie $db:$mode:$x\n"; if ($x == -1) { return undef; } push(@db,$x); $TIEDB{$x}=$db; } bless \@db; } sub DESTROY { my($obj,$k)=@_; #print STDERR "Destroy $$obj\n"; foreach $k (@$obj) { &Fame::HLI::fameclose($k); delete($TIEDB{$k}); } } # # convert a string ident to a date # # : [+-offset] [ , [+-offset] ] # # date may be "*". # sub getident { my ($key,@dbl)=@_; my ($k,$sdate,$edate)=($key =~ /([^:]+):?([^,]*),?(.*)/); #split(/[,;]/,$key); my ($sy, $sp, $ey, $ep, @i, $db); $db=&famefind($k,@dbl); #print STDERR "search @dbl $k $db\n"; if ($db<0) { return undef; } #print STDERR "found $db $k $sdate $edate\n"; @i=&Fame::HLI::famegetinfo($db,$k); #print STDERR "info $k=",join(":",@i),"\n"; if ($i[0] == &Fame::HLI::HSERIE) { if (!$sdate) { $sdate="*"; } if (!$edate) { $edate=$sdate; } if ($sdate eq "*") { ($sy, $sp)=@i[5,6]; } else { ($sy,$sp)=&getdate($sdate, $i[2]); } if ($edate eq "*") { ($ey, $ep)=@i[7,8]; } else { ($ey,$ep)=&getdate($edate, $i[2]); } if ($i[2] != &Fame::HLI::HCASEX && ($sy == 0 || $ey == 0)) { return undef; } #print STDERR "getdate $db $k $sy $sp $ey $ep\n"; return ($db,$k,"$sy:$sp","$ey:$ep"); } else { return ($db,$k,"0:0","0:0"); } } sub FETCH { my ($obj, $key)=@_; #my (@x)=(); # return db codes for all open databases if ($key eq "dbcodes") { return $obj; } # return names for open databases if ($key eq "dblist") { @x=(); my ($k); foreach $k (@$obj) { push(@x,$TIEDB{$k}); } return bless \@x; } #print STDERR "read0 @$obj $key\n"; my ($db,$k,$start,$end)=&getident($key,@$obj); if (!$k) { return undef; } #print STDERR "read $db $k : $sy $sp $ey $ep\n"; @x=&Read($db, $k, $start, $end); bless \@x; } sub STORE { my ($obj, $key, $val)=@_; my (@v); if (ref($val)) { @v=@$val; } else { @v=($val); } my ($db,$k,$start)=&getident($key,@$obj); #print STDERR "write $db $k $start ",join(":",@v),"\n"; if (!$k) { return undef; } &Write($db, $k, $start, @v); 1; } sub DELETE { my($obj, $key)=@_; my ($status); $db=&famefind($key,@$obj); &Fame::HLI::cfmdlob($status, $db, $key); if ($status == &Fame::HLI::HSUCC) { return 1; } else { return 0; } } sub EXISTS { my ($obj, $key)=@_; my($i)=&famefind($key, @$obj); if ($i<0) { return 0; } else { return 1; } } sub FIRSTKEY { my ($obj)=@_; my ($status, $name, $class, $type, $freq); my ($w)=($WILD); @WILDDB=@$obj; &Fame::HLI::cfminwc($status, $WILDDB[0], $w); &Fame::HLI::cfmnxwc($status, $WILDDB[0], $name, $class, $type, $freq); #print STDERR "Get First $obj : $status, $name, $class, $type, $freq\n"; if ($status==&Fame::HLI::HSUCC) { return $name; } else { return undef; } } sub NEXTKEY { my ($obj, $last)=@_; my ($status, $name, $class, $type, $freq); my ($w)=($WILD); &Fame::HLI::cfmnxwc($status, $WILDDB[0], $name, $class, $type, $freq); #print STDERR "Start Get Next $obj : $status, $name, $class, $type, $freq\n"; if ($status==&Fame::HLI::HSUCC) { return $name; } else { shift(@WILDDB); if ($#WILDDB<0) { return undef; } &Fame::HLI::cfminwc($status, $WILDDB[0], $w); &Fame::HLI::cfmnxwc($status, $WILDDB[0], $name, $class, $type, $freq); if ($status==&Fame::HLI::HSUCC) { return $name; } else { return undef; } } } 1;