partial support for tag expression as binary tree
authorIan Beckwith <ianb@erislabs.net>
Wed, 6 Oct 2010 01:11:37 +0000 (02:11 +0100)
committerIan Beckwith <ianb@erislabs.net>
Wed, 6 Oct 2010 01:11:37 +0000 (02:11 +0100)
lib/ID3FS/Path.pm
lib/ID3FS/Path/Node.pm [new file with mode: 0644]

index de55ce1..0ca6711 100644 (file)
@@ -8,11 +8,14 @@ use ID3FS::PathElement::Boolean;
 use ID3FS::PathElement::File;
 use ID3FS::PathElement::Tag;
 use ID3FS::PathElement::Tagval;
+use ID3FS::Path::Node;
 
 our ($STATE_INVALID, $STATE_ROOT, $STATE_TAG, $STATE_TAGVAL,
      $STATE_BOOLEAN, $STATE_ALBUMS, $STATE_TRACKLIST,
      $STATE_FILE)=(0..7);
 
+our %priorities=( "OR" => 0, "AND" => 1, "NOT" => 2 );
+
 sub new
 {
     my $proto=shift;
@@ -294,6 +297,7 @@ sub parse
            $self->state($STATE_INVALID);
        }
     }
+    $self->{tagtree}=$self->elements_to_tree(@{$self->{elements}});
 }
 
 sub state
@@ -303,4 +307,55 @@ sub state
     return $self->{state};
 }
 
+sub elements_to_tree
+{
+    my($self, @elements)=@_;
+    my $op=undef;
+    my $top=undef;
+    my $node=undef;
+    my $lastop=undef;
+    use Data::Dumper;
+    while(my $element=shift @elements)
+    {
+       my $tag;
+       if(ref($element) eq "ID3FS::PathElement::Boolean")
+       {
+           $lastop=$op;
+           $op=$element->{name};
+#          print "BOOL: $op\n";
+       }
+       if(ref($element) eq "ID3FS::PathElement::Tag")
+       {
+           $tag=$element->{name};
+           while(@elements && ref($elements[0]) eq "ID3FS::PathElement::Tag")
+           {
+               $tag .= "/" . (shift @elements)->{name};
+           }
+#          print "TAG: $tag\n";
+           my $node=ID3FS::Path::Node->new($tag);
+           if(!$top)
+           {
+               $top=$node;
+           }
+           elsif($op)
+           {
+               my $nextop=undef;
+               if(!defined($lastop) || ($priorities{$lastop} >= $priorities{$op}))
+               {
+                   $top=ID3FS::Path::Node->new($node, $op, $top);
+               }
+               else
+               {
+                   $top=ID3FS::Path::Node->new($top, $op, $node);
+               }
+           }
+           else
+           {
+               die ("FAIL - SHOULD NOT HAPPEN\n");
+           }
+       }
+    }
+    print($top->print(), "\n") if $top;
+}
+
 1;
diff --git a/lib/ID3FS/Path/Node.pm b/lib/ID3FS/Path/Node.pm
new file mode 100644 (file)
index 0000000..08c2088
--- /dev/null
@@ -0,0 +1,59 @@
+package ID3FS::Path::Node;
+
+use strict;
+use warnings;
+
+sub new
+{
+    my $proto=shift;
+    my $class=ref($proto) || $proto;
+    my $self={};
+    bless($self,$class);
+
+    $self->left(shift);
+    $self->op(shift);
+    $self->right(shift);
+
+    return $self;
+}
+
+sub set
+{
+    my($self, $name, $val)=@_;
+    if(defined($val))
+    {
+       $self->{$name}=$val;
+    }
+    return $self->{$name};
+}
+
+sub left  { return shift->set("left",  shift); }
+sub right { return shift->set("right", shift); }
+sub op    { return shift->set("op",    shift); }
+
+sub print
+{
+    my($self)=@_;
+    my $op=$self->op();
+    my $left=$self->left();
+    my $right=$self->right();
+    return undef unless($left || $right);
+    my $str .= $self->print_node($left);
+    $str .= " $op " if($op);
+    $str .= $self->print_node($right);
+    if($op || ($left && $right))
+    {
+       $str="(" . $str . ")";
+    }
+    return $str;
+}
+
+sub print_node
+{
+    my($self, $node)=@_;
+    return "" unless(defined($node));
+    return $node->print() if(ref($node) eq "ID3FS::Path::Node");
+    return $node;
+}
+
+1;