File Coverage

blib/lib/Data/GUID/Any.pm
Criterion Covered Total %
statement 186 187 99.4
branch 9 12 75.0
condition 1 3 33.3
subroutine 67 67 100.0
pod n/a
total 263 269 97.7


line stmt bran cond sub pod time code
1 1     1   640 use 5.006;
  1     1   3  
  1     1   140  
  1     1   3  
  1     1   85553  
  1     1   4  
  1     1   11682  
  1     1   5  
  1     1   6547  
  1     1   4  
  1         493  
  1         3  
  1         8372  
  1         4  
  1         6586  
  1         4  
  1         489  
  1         2  
  1         8085  
  1         8  
2 1     1   4 use strict;
  1     1   2  
  1     1   16  
  1     1   5  
  1     1   1  
  1     1   19  
  1     1   4  
  1     1   2  
  1     1   16  
  1     1   5  
  1         1  
  1         35  
  1         5  
  1         2  
  1         17  
  1         4  
  1         2  
  1         18  
  1         10  
  1         5  
  1         32  
  1         4  
  1         2  
  1         19  
  1         5  
  1         1  
  1         33  
  1         9  
  1         3  
  1         32  
3 1     1   4 use warnings;
  1     1   1  
  1     1   35  
  1     1   4  
  1     1   1  
  1     1   35  
  1     1   4  
  1     1   2  
  1     1   43  
  1     1   6  
  1         2  
  1         84  
  1         5  
  1         1  
  1         36  
  1         3  
  1         2  
  1         51  
  1         6  
  1         5  
  1         58  
  1         3  
  1         2  
  1         36  
  1         4  
  1         2  
  1         37  
  1         11  
  1         2  
  1         62  
4             package Data::GUID::Any;
5             # ABSTRACT: Generic interface for GUID/UUID creation
6              
7             our $VERSION = '0.005';
8              
9 1     1   8 use IPC::Cmd;
  1     1   47163  
  1     1   38  
  1     1   4  
  1     1   2  
  1     1   36  
  1     1   5  
  1     1   1  
  1     1   51  
  1     1   12  
  1         2  
  1         52  
  1         5  
  1         2  
  1         30  
  1         10  
  1         2  
  1         41  
  1         5  
  1         6  
  1         44  
  1         4  
  1         2  
  1         29  
  1         5  
  1         1  
  1         37  
  1         9  
  1         5  
  1         37  
10 1     1   7 use Exporter;
  1     1   1  
  1     1   766  
  1     1   4  
  1     1   8  
  1     1   119  
  1     1   5  
  1     1   1  
  1     1   110  
  1     1   10  
  1         2  
  1         144  
  1         4  
  1         2  
  1         83  
  1         4  
  1         2  
  1         113  
  1         5  
  1         6  
  1         131  
  1         5  
  1         1  
  1         87  
  1         5  
  1         2  
  1         111  
  1         10  
  1         2  
  1         102  
11             our @ISA = qw/Exporter/;
12             our @EXPORT_OK = qw/ guid_as_string v1_guid_as_string v4_guid_as_string/;
13              
14             our ($Using_vX, $Using_v1, $Using_v4) = ("") x 3;
15             our $UC = 1;
16              
17             #--------------------------------------------------------------------------#
18              
19             my $hex = "a-z0-9";
20              
21             # case insensitive, since used to check if generators are functioning
22             sub _looks_like_guid {
23 3     3   5 my $guid = shift;
24 3         69 return $guid =~ /[$hex]{8}-[$hex]{4}-[$hex]{4}-[$hex]{4}-[$hex]{12}/i;
25             }
26              
27             #--------------------------------------------------------------------------#
28              
29             sub _xc {
30 5 100   5   606 return $UC ? uc($_[0]) : lc($_[0]);
31             }
32              
33             #--------------------------------------------------------------------------#
34              
35             # state variables for generator closures
36             my ($dumt_v1, $dumt_v4, $uuid_v1, $uuid_v4) = (undef) x 4; # reset if reloaded
37              
38             my %generators = (
39             # v1 or v4
40             'Data::UUID::MT' => {
41             type => 'module',
42             v1 => sub {
43             $dumt_v1 ||= Data::UUID::MT->new(version => 1);
44             return _xc( $dumt_v1->create_string );
45             },
46             v4 => sub {
47             $dumt_v4 ||= Data::UUID::MT->new(version => 4);
48             return _xc( $dumt_v4->create_string );
49             },
50             },
51             'Data::UUID::LibUUID' => {
52             type => 'module',
53             v1 => sub { return _xc( Data::UUID::LibUUID::new_uuid_string(2) ) },
54             v4 => sub { return _xc( Data::UUID::LibUUID::new_uuid_string(4) ) },
55             vX => sub { return _xc( Data::UUID::LibUUID::new_uuid_string() ) },
56             },
57             'UUID::Tiny' => {
58             type => 'module',
59 2     2   11 v1 => sub { return _xc( UUID::Tiny::create_UUID_as_string(UUID::Tiny::UUID_V1()) ) },
60 3     3   1387 v4 => sub { return _xc( UUID::Tiny::create_UUID_as_string(UUID::Tiny::UUID_V4()) ) },
61             },
62             'uuid' => {
63             type => 'binary',
64             v1 => sub {
65             $uuid_v1 ||= IPC::Cmd::can_run('uuid');
66             chomp( my $guid = qx/$uuid_v1 -v1/ ); return _xc( $guid );
67             },
68             v4 => sub {
69             $uuid_v4 ||= IPC::Cmd::can_run('uuid');
70             chomp( my $guid = qx/$uuid_v4 -v4/ ); return _xc( $guid );
71             },
72             },
73             # v1 only
74             'Data::GUID' => {
75             type => 'module',
76             v1 => sub { return _xc( Data::GUID->new->as_string ) },
77             },
78             'Data::UUID' => {
79             type => 'module',
80             v1 => sub { return _xc( Data::UUID->new->create_str ) },
81             },
82             # system dependent or custom
83             'UUID' => {
84             type => 'module',
85             vX => sub { my ($u,$s); UUID::generate($u); UUID::unparse($u, $s); return _xc( $s ) },
86             },
87             'Win32' => {
88             type => 'module',
89             vX => sub { my $guid = Win32::GuidGen(); return _xc( substr($guid,1,-1) ) },
90             },
91             'APR::UUID' => {
92             type => 'module',
93             vX => sub { return _xc( APR::UUID->new->format ) },
94             },
95             );
96              
97             our $NO_BINARY; # for testing
98             sub _is_available {
99 19     19   28 my ($name) = @_;
100 19 100       39 if ( $generators{$name}{type} eq 'binary' ) {
101 3 50       14 return $NO_BINARY ? undef : IPC::Cmd::can_run($name);
102             }
103             else {
104 16         638 return eval "require $name";
105             }
106             }
107              
108             sub _best_generator {
109 3     3   5 my ($list) = @_;
110 3         5 for my $option ( @$list ) {
111 19         1130 my ($name, $version) = @$option;
112 19 50       40 next unless my $g = $generators{$name};
113 19 100       28 next unless _is_available($name);
114             return ($name, $g->{$version})
115 3 50 33     19 if $g->{$version} && _looks_like_guid( $g->{$version}->() );
116             }
117 0         0 return;
118             }
119              
120             #--------------------------------------------------------------------------#
121              
122             my %sets = (
123             any => [
124             ['Data::UUID::MT' => 'v4'],
125             ['Data::GUID' => 'v1'],
126             ['Data::UUID' => 'v1'],
127             ['Data::UUID::LibUUID' => 'vX'],
128             ['UUID' => 'vX'],
129             ['Win32' => 'vX'],
130             ['uuid' => 'v1'],
131             ['APR::UUID' => 'vX'],
132             ['UUID::Tiny' => 'v1'],
133             ],
134             v1 => [
135             ['Data::UUID::MT' => 'v1'],
136             ['Data::GUID' => 'v1'],
137             ['Data::UUID' => 'v1'],
138             ['Data::UUID::LibUUID' => 'v1'],
139             ['uuid' => 'v1'],
140             ['UUID::Tiny' => 'v1'],
141             ],
142             v4 => [
143             ['Data::UUID::MT' => 'v4'],
144             ['Data::UUID::LibUUID' => 'v4'],
145             ['uuid' => 'v4'],
146             ['UUID::Tiny' => 'v4'],
147             ],
148             );
149              
150 3     3   13 sub _generator_set { return $sets{$_[0]} }
151              
152             {
153 1     1   6 no warnings qw/once redefine/;
  1     1   3  
  1     1   164  
  1     1   814  
  1     1   2  
  1     1   168  
  1     1   826  
  1     1   2  
  1     1   181  
  1     1   983  
  1         2  
  1         202  
  1         774  
  1         2  
  1         174  
  1         817  
  1         2  
  1         160  
  1         979  
  1         4  
  1         203  
  1         747  
  1         2  
  1         160  
  1         780  
  1         2  
  1         158  
  1         967  
  1         6  
  1         246  
154             {
155             my ($n, $s) = _best_generator(_generator_set("any"));
156             die "Couldn't find a GUID provider" unless $n;
157             *guid_as_string = $s;
158             $Using_vX = $n;
159             }
160             {
161             my ($n, $s) = _best_generator(_generator_set("v1"));
162             *v1_guid_as_string = $s || sub { die "No v1 GUID provider found\n" };
163             $Using_v1 = $n || '';
164             }
165             {
166             my ($n, $s) = _best_generator(_generator_set("v4"));
167             *v4_guid_as_string = $s || sub { die "No v4 GUID provider found\n" };
168             $Using_v4 = $n || '';
169             }
170             }
171              
172             1;
173              
174             __END__