File Coverage

blib/lib/Mac/PropertyList/XS.pm
Criterion Covered Total %
statement 21 23 91.3
branch n/a
condition n/a
subroutine 8 8 100.0
pod n/a
total 29 31 93.5


line stmt bran cond sub pod time code
1             =head1 NAME
2              
3             Mac::PropertyList::XS - work with Mac plists at a low level, really fast
4              
5             =cut
6              
7             package Mac::PropertyList::XS;
8              
9             =head1 SYNOPSIS
10              
11             See L and L
12              
13             =head1 DESCRIPTION
14              
15             L was my first attempt to speed up property-list
16             parsing. It achieves about a 30x speed boost, but large files still take
17             too long for my taste. This module addresses some remaining speed gains
18             by implementing some expensive operations in C.
19              
20             This module is intended to be a drop-in replacement for
21             L, which is itself a drop-in replacement for
22             L.
23              
24             =cut
25              
26 18     18   270794 use 5.008008;
  18         81  
27 18     18   122 use strict;
  18         50  
  18         477  
28 18     18   103 use warnings;
  18         48  
  18         574  
29 18     18   104 use Carp;
  18         40  
  18         1463  
30              
31             require Exporter;
32 18     18   9017 use AutoLoader;
  18         23253  
  18         168  
33              
34             # Passthrough function
35 18     18   8936 use Mac::PropertyList qw(plist_as_string);
  18         638405  
  18         1574  
36 18     18   9794 use Mac::PropertyList::SAX qw(create_from_ref create_from_hash create_from_array);
  18         663955  
  18         1664  
37 18     18   12451 use XML::Parser;
  0            
  0            
38              
39             use base qw(Exporter);
40              
41             our @EXPORT_OK = qw(
42             parse_plist
43             parse_plist_fh
44             parse_plist_file
45             parse_plist_string
46             plist_as_string
47             create_from_ref
48             create_from_hash
49             create_from_array
50             );
51              
52             our %EXPORT_TAGS = (
53             all => \@EXPORT_OK,
54             create => [ qw(create_from_ref create_from_hash create_from_array plist_as_string) ],
55             parse => [ qw(parse_plist parse_plist_fh parse_plist_file parse_plist_string) ],
56             );
57              
58             our $VERSION = '0.03';
59             our $XS_VERSION = $VERSION;
60             $VERSION = eval $VERSION; # see L
61              
62             sub AUTOLOAD {
63             # This AUTOLOAD is used to 'autoload' constants from the constant()
64             # XS function.
65              
66             my $constname;
67             our $AUTOLOAD;
68             ($constname = $AUTOLOAD) =~ s/.*:://;
69             croak "&Mac::PropertyList::XS::constant not defined" if $constname eq 'constant';
70             my ($error, $val) = constant($constname);
71             if ($error) { croak $error; }
72             {
73             no strict 'refs';
74             # Fixed between 5.005_53 and 5.005_61
75             #XXX if ($] >= 5.00561) {
76             #XXX *$AUTOLOAD = sub () { $val };
77             #XXX }
78             #XXX else {
79             *$AUTOLOAD = sub { $val };
80             #XXX }
81             }
82             goto &$AUTOLOAD;
83             }
84              
85             require XSLoader;
86             XSLoader::load('Mac::PropertyList::XS', $XS_VERSION);
87              
88             =head1 EXPORTS
89              
90             By default, no functions are exported. Specify individual functions to export
91             as usual, or use the tags ':all', ':create', and ':parse' for the appropriate
92             sets of functions (':create' includes the create* functions as well as
93             plist_as_string; ':parse' includes the parse* functions).
94              
95             =head1 FUNCTIONS
96              
97             =over 4
98              
99             =item parse_plist_file
100              
101             See L
102              
103             =cut
104              
105             sub parse_plist_file
106             {
107             my $file = shift;
108              
109             if (ref $file) {
110             _parse(parse_file => $file);
111             } else {
112             carp("parse_plist_file: file [$file] does not exist!"), return unless -e $file;
113             open my $fh, "<", $file;
114             _parse(parse_file => $fh);
115             }
116             }
117              
118             sub _parse {
119             # shift off first param in case we use `goto` later (leaving @_ with $data)
120             my $sub = shift;
121             my ($data) = @_;
122              
123             my $first;
124             my $fh;
125             my $delegate;
126              
127             # read initial bytes of file
128             # if we have a binary plist, delegate to Mac::PropertyList
129             if ($sub eq "parse_uri") {
130             open $fh, "<", $_[0];
131             $sub = "parse_file";
132             $_[0] = $fh;
133             # delegate will be set below
134             }
135              
136             if ($sub eq "parse_file") {
137             read $_[0], $first, length "bplist";
138             seek $_[0], 0, 0 or die "Can't seek given filehandle"; # seek back to beginning
139             $delegate = \&Mac::PropertyList::parse_plist_fh;
140             } elsif ($sub eq "parse_string") {
141             $first = $_[0];
142             $delegate = \&Mac::PropertyList::parse_plist;
143             }
144              
145             if ($first =~ /^bplist/) {
146             # binary plist -- delegate to non-SAX module
147             goto $delegate;
148             } else {
149             my $p = new XML::Parser(Handlers => { Init => \&handle_init,
150             Start => \&handle_start,
151             End => \&handle_end,
152             Char => \&handle_char,
153             Final => \&handle_final });
154             return $p->parse($data);
155             }
156             }
157              
158             =item parse_plist_fh
159              
160             See L
161              
162             =cut
163              
164             sub parse_plist_fh { _parse(parse_file => @_) }
165              
166             =item parse_plist
167              
168             See L
169              
170             =cut
171              
172             sub parse_plist { _parse(parse_string => @_) }
173              
174             =item parse_plist_string
175              
176             An alias to parse_plist, provided for better regularity compared to Perl SAX.
177              
178             =cut
179              
180             *parse_plist_string = \&parse_plist;
181              
182             =item create_from_ref( HASH_REF | ARRAY_REF )
183              
184             Create a plist from an array or hash reference.
185              
186             The values of the hash can be simple scalars or references. Hash and array
187             references are handled recursively, and L objects are output
188             correctly. All other scalars are treated as strings (use L
189             objects to represent other types of scalars).
190              
191             Returns a string representing the reference in serialized plist format.
192              
193             =item create_from_hash( HASH_REF )
194              
195             Provided for backward compatibility with L: aliases
196             create_from_ref.
197              
198             =item create_from_array( ARRAY_REF )
199              
200             Provided for backward compatibility with L: aliases
201             create_from_ref.
202              
203             =back
204              
205             =head1 BUGS / CAVEATS
206              
207             Certainly !
208              
209             =head1 SUPPORT
210              
211             Please contact the author with bug reports or feature requests.
212              
213             =head1 AUTHOR
214              
215             Darren M. Kulp, C<< >>
216              
217             =head1 THANKS
218              
219             brian d foy, who created the L module whose tests were
220             appropriated for this module.
221              
222             =head1 SEE ALSO
223              
224             L, the inspiration for this module.
225              
226             =head1 COPYRIGHT AND LICENSE
227              
228             Copyright (C) 2009-2017 by Darren Kulp
229              
230             This library is free software; you can redistribute it and/or modify
231             it under the same terms as Perl itself, either Perl version 5.8.4 or,
232             at your option, any later version of Perl 5 you may have available.
233              
234             =cut
235              
236             1;
237             __END__