diff -r 000000000000 -r beb51793110d Symbian/SysDefToText/SysDefParser.pm --- /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 => , [-parser => ]) : creates a +# instance. is the instance to which the parser callbacks +# are dispatched. is an optional alternative parser client +# package to use instead of the default XML::Parser class. +# +# parse(): parse the XML data from filehandle 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