Symbian/SysDefToText/SysDefParser.pm
changeset 0 beb51793110d
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Symbian/SysDefToText/SysDefParser.pm	Mon Jan 18 21:35:57 2010 +0200
@@ -0,0 +1,131 @@
+#
+# Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+# All rights reserved.
+# This component and the accompanying materials are made available
+# under the terms of "Eclipse Public License v1.0"
+# which accompanies this distribution, and is available
+# at the URL "http://www.eclipse.org/legal/epl-v10.html".
+#
+# Initial Contributors:
+# Nokia Corporation - initial contribution.
+#
+# Contributors:
+#
+# Description:
+#
+#-------------------------------------------------------------------------------
+# package: SysDefParser
+#
+# usage: Wrapper for an XML parser to dispatch callbacks to a client object which
+#    analyses the parsed XML data. The auxiliary package SysDefParser::Dispatcher
+#    acts as an intermediary between the parser and the client to convert function
+#    callbacks to method callbacks using perl's AUTOLOAD mechanism.
+#
+# public methods:
+#
+#    new(-client => <client reference>, [-parser => <package name>]) : creates a
+#        instance. <client reference> is the instance to which the parser callbacks
+#        are dispatched. <package name> is an optional alternative parser client
+#        package to use instead of the default XML::Parser class.
+#
+#    parse(<fileh>): parse the XML data from filehandle <fileh> dispatching
+#        callbacks to the client object.
+#         
+#-------------------------------------------------------------------------------
+
+package SysDefParser;
+use strict;
+
+sub new
+{
+    my ($class, %args) = @_;
+    my $self = bless {}, $class;
+    $self->{client} = delete $args{-client};
+
+    if (exists $args{-parser})
+    {
+        $args{Pkg} = 'SysDefParser::Dispatcher';
+        require $args{-parser};
+        $self->{parser} = $args{-parser}->createParser(%args);
+    }
+    else
+    {
+        $self->{parser} = $class->_createParser(%args);
+    }
+
+    return $self;
+}
+
+sub _createParser
+{
+    my ($class, %args) = @_;
+    require XML::Parser;
+    return XML::Parser->new
+           (
+               Style        => 'Subs',
+               Pkg          => 'SysDefParser::Dispatcher',
+               ErrorContext => 2
+           );
+}
+
+my $PARSERCLIENT = undef;
+
+sub _client { return $PARSERCLIENT; }
+
+sub parse
+{
+    my ($self, $fileh) = @_;
+
+    # we can't pass any context down to the underlying parser so that we can work out which
+    # object any callbacks from the parser are associated with so, assuming that the parser will
+    # not be called in a re-entrant fashion, we store the context at this point, so that we can
+    # then dispatch the callbacks from the parsers 'parse' method to those methods of the saved
+    # $PARSERCLIENT instance.
+
+    die "Fatal: client object not set\n" if ! defined $self->{client};
+    die "Fatal: parser client object already set\n" if defined $PARSERCLIENT;
+    $PARSERCLIENT = $self->{client};
+
+    # call the parser, callbacks will be dispatched to sub AUTOLOAD in SysDefParser::Dispatcher
+
+    my $rv =$self->{parser}->parse($fileh);
+
+    # finished parsing, unset the context
+
+    $PARSERCLIENT = undef;
+
+    return $rv;
+}
+
+#-------------------------------------------------------------------------------
+# package SysDefParser::Dispatcher
+#
+# usage: Internal package. Uses AUTOLOAD mechanism to receive parser callbacks and
+#    convert them to object method calls on teh client object.
+#
+#-------------------------------------------------------------------------------
+package SysDefParser::Dispatcher;
+use strict;
+
+sub AUTOLOAD
+{
+    my @ARGS = @_;
+
+    my $client = SysDefParser::_client();
+
+    die "Fatal: parser client object not set\n" if ! defined $client;
+
+    # translate the called back function name to the client method name
+    my $clientpkg = ref($client);
+    my $method = $SysDefParser::Dispatcher::AUTOLOAD;
+
+    $method =~ s/^SysDefParser::Dispatcher/$clientpkg/;
+
+    # dispatch the parser's callback to the client object (if implemented by client)
+    $client->$method(@ARGS) if $client->can($method);
+}
+
+#-------------------------------------------------------------------------------
+# -EOF-
+#-------------------------------------------------------------------------------
+1;
\ No newline at end of file