Much wider support for Catacomb in all its glory.
[catacomb-perl] / Catacomb / Key.pm
diff --git a/Catacomb/Key.pm b/Catacomb/Key.pm
new file mode 100644 (file)
index 0000000..6f84492
--- /dev/null
@@ -0,0 +1,189 @@
+# -*-perl-*-
+#
+# $Id$
+#
+# Key management
+#
+# (c) 2004 Straylight/Edgeware
+#
+
+#----- Licensing notice -----------------------------------------------------
+#
+# This file is part of the Perl interface to Catacomb.
+#
+# Catacomb/Perl is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+# 
+# Catacomb/Perl is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with Catacomb/Perl; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#----- Key data -------------------------------------------------------------
+
+package Catacomb::Key::StructData;
+use Carp;
+use Catacomb::Base;
+
+sub TIEHASH { bless [$_[1], []], $_[0]; }
+sub FETCH { Catacomb::Key::Data::StructItem->new($_[0][0], $_[1]); }
+sub EXISTS { !!$_[0][0]->_get->structfind($_[1]); }
+sub DELETE { $_[0][0]->_get->structdel($_[1]); }
+sub CLEAR { $_[0][0]->_get()->setstruct(); }
+sub STORE {
+  my ($me, $k, $v) = @_;
+  $me->[0]->_get()->structcreate($k)->set($v);
+}
+sub FIRSTKEY {
+  my ($me) = @_;
+  my $kd = $me->[0]->_get();
+  my $i = $kd->structiter();
+  my @k = ();
+  while (my $k = $i->next()) {
+    push(@k, $k);
+  }
+  $me->[1] = \@k;
+  return shift(@k);
+}
+sub NEXTKEY { shift(@{$_[0][1]}); }
+
+package Catacomb::Key::DataRef;
+use Carp;
+use Catacomb::Base;
+use Catacomb::MP;
+use Catacomb::EC;
+sub _adopt {
+  my $kd = shift;
+  defined($kd) or return;
+  $kd = bless [$kd], Catacomb::Key::Data;
+  return wantarray ? ($kd, @_) : $kd;
+}
+sub new { my $me = shift(@_); bless [@_], $me; }
+sub _proxy { my ($op, $kd, @args) = @_; &$op($kd->_get(), @args); }
+
+sub setbinary { _proxy(\&Catacomb::Key::DataImpl::setbinary, @_); }
+sub setencrypted { _proxy(\&Catacomb::Key::DataImpl::setencrypted, @_); }
+sub setmp { _proxy(\&Catacomb::Key::DataImpl::setec, @_); }
+sub setstring { _proxy(\&Catacomb::Key::DataImpl::setstring, @_); }
+sub setec { _proxy(\&Catacomb::Key::DataImpl::setec, @_); }
+
+sub flags { _proxy(\&Catacomb::Key::DataImpl::flags, @_); }
+
+sub getbinary { _proxy(\&Catacomb::Key::DataImpl::getbinary, @_); }
+sub getencrypted { _proxy(\&Catacomb::Key::DataImpl::getencrypted, @_); }
+sub getmp { _proxy(\&Catacomb::Key::DataImpl::getmp, @_); }
+sub getstring { _proxy(\&Catacomb::Key::DataImpl::getstring, @_); }
+sub getec { _proxy(\&Catacomb::Key::DataImpl::getec, @_); }
+
+sub setstruct { _proxy(\&Catacomb::Key::DataImpl::setstruct, @_); }
+sub structfind { Catacomb::Key::Data::StructItem->new($_[0], $_[1]); }
+sub structcreate {
+  _proxy(\&Catacomb::Key::DataImpl::structcreate, @_);
+  Catacomb::Key::Data::StructItem->new($_[0], $_[1]);
+}
+sub structiter { _proxy(\&Catacomb::Key::DataImpl::structiter, @_); }
+sub structdel { _proxy(\&Catacomb::Key::DataImpl::structdel, @_); }
+sub structopen {  my %h; tie %h, Catacomb::Key::StructData, $_[0]; \%h; }
+
+sub copy {
+  croak("Usage: Catacomb::Key::Data::Ref::copy(kd, kkd, [filter])")
+    unless @_ >= 2 && @_ <= 3;
+  my $kd = Catacomb::Key::Data->new();
+  $kd->_get()->set($_[0]->_get(), $_[1]);
+  return $kd;
+}
+sub lock { _adopt(_proxy(\&Catacomb::Key::DataImpl::lock, @_)); }
+sub unlock { _adopt(_proxy(\&Catacomb::Key::DataImpl::unlock, @_)); }
+sub plock { _adopt(_proxy(\&Catacomb::Key::DataImpl::plock, @_)); }
+sub punlock { _adopt(_proxy(\&Catacomb::Key::DataImpl::punlock, @_)); }
+sub read { _adopt(Catacomb::Key::DataImpl::read(@_)); }
+sub write { _proxy(\&Catacomb::Key::DataImpl::write, @_); }
+sub decode { _adopt(Catacomb::Key::DataImpl::decode(@_)); }
+sub encode { _proxy(\&Catacomb::Key::DataImpl::encode, @_); }
+
+package Catacomb::Key::Data;
+use Carp;
+@ISA = qw(Catacomb::Key::DataRef);
+sub _get { $_[0][0]; }
+## Perl will randomly zap my reference during cleanup.  Just pretend
+## we didn't notice.
+sub DESTROY { $_[0][0]->free() if defined $_[0][0]; }
+sub new {
+  croak("Usage: Catacomb::Key::Data::new(me)") unless @_ == 1;
+  Catacomb::Key::DataRef::_adopt(Catacomb::Key::DataImpl->new());
+}
+
+package Catacomb::Key::Data::StructItem;
+@ISA = qw(Catacomb::Key::DataRef);
+sub _get { $_[0][0]->_get()->structfind($_[0][1]); }
+
+package Catacomb::Key::Data::KeyData;
+@ISA = qw(Catacomb::Key::DataRef);
+sub _get { $_[0][0]->_data(); }
+
+#----- Actual keys ----------------------------------------------------------
+
+package Catacomb::Key::Attrs;
+use Carp;
+
+sub TIEHASH { bless [$_[1], []], $_[0]; }
+sub FETCH { $_[0][0]->getattr($_[1]); }
+sub EXISTS { defined($_[0][0]->getattr($_[1])); }
+sub STORE { $_[0][0]->putattr($_[1], $_[2]); }
+sub DELETE { $_[0][0]->putattr($_[1]); }
+sub FIRSTKEY {
+  my ($me) = @_;
+  my $k = $me->[0];
+  my $i = $k->attriter();
+  my @a;
+  while (my $a = $i->next()) { push(@a, $a); }
+  $me->[1] = \@a;
+  return shift(@a);
+}
+sub NEXTKEY { shift(@{$_[0][1]}); }
+
+package Catacomb::Key;
+
+sub attrs {
+  croak("Usage: Catacomb::Key::attrs(k)") unless @_ == 1;
+  my %a;
+  tie %a, Catacomb::Key::Attrs, @_;
+  return \%a;
+}
+
+sub data {
+  croak("Usage: Catacomb::Key::data(k)") unless @_ == 1;
+  return Catacomb::Key::Data::KeyData->new($_[0]);
+}
+
+package Catacomb::Key::File;
+use Carp;
+use Catacomb::Base;
+
+sub qtag {
+  croak("Usage: Catacomb::Key::File::qtag(kf, tag)") unless @_ == 2;
+  my ($kf, $tag) = @_;
+  my @q = ();
+  if ($tag =~ /^([^.]*)\.(.*)$/) {
+    $tag = $1;
+    @q = split(/\./, $2);
+  }
+  my $k = $kf->bytag($tag) or return;
+  my $d = $k->data();
+  my $f = $k->fulltag();
+  foreach my $t (@q) {
+    $d = $d->structfind($t) or return;
+    $f .= "." . $t;
+  }
+  return $k, $d, $f;
+}
+
+#----- That's all, folks ----------------------------------------------------
+
+1;