line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Proquint; |
2
|
1
|
|
|
1
|
|
227725
|
use strict; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
28
|
|
3
|
1
|
|
|
1
|
|
5
|
use warnings; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
27
|
|
4
|
1
|
|
|
1
|
|
4
|
use Carp (); |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
12
|
|
5
|
1
|
|
|
1
|
|
443
|
use Exporter::Tiny; |
|
1
|
|
|
|
|
3067
|
|
|
1
|
|
|
|
|
8
|
|
6
|
1
|
|
|
1
|
|
893
|
use Socket (qw/inet_pton inet_ntop AF_INET AF_INET6/); |
|
1
|
|
|
|
|
3791
|
|
|
1
|
|
|
|
|
970
|
|
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
our $VERSION = '1.0.0_3'; |
9
|
|
|
|
|
|
|
our @ISA = 'Exporter::Tiny'; |
10
|
|
|
|
|
|
|
our @EXPORT_OK = ( |
11
|
|
|
|
|
|
|
qw/ |
12
|
|
|
|
|
|
|
uint2proquint proquint2uint |
13
|
|
|
|
|
|
|
hex2proquint proquint2hex |
14
|
|
|
|
|
|
|
ip2proquint proquint2ip |
15
|
|
|
|
|
|
|
/ |
16
|
|
|
|
|
|
|
); |
17
|
|
|
|
|
|
|
our @EXPORT_TAGS = ( all => \@EXPORT_OK ); |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
my @UINT_TO_CONSONANT = (qw/ b d f g h j k l m n p r s t v z /); |
20
|
|
|
|
|
|
|
my @UINT_TO_VOWEL = (qw/ a i o u /); |
21
|
|
|
|
|
|
|
my $CHARS_PER_CHUNK = 5; |
22
|
|
|
|
|
|
|
my $MASK_LAST2 = 0x3; |
23
|
|
|
|
|
|
|
my $MASK_LAST4 = 0xF; |
24
|
|
|
|
|
|
|
my $SEPARATOR = '-'; |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
my %CONSONANT_TO_UINT = do { |
27
|
|
|
|
|
|
|
my $i = 0; |
28
|
|
|
|
|
|
|
map { $_ => $i++ } @UINT_TO_CONSONANT; |
29
|
|
|
|
|
|
|
}; |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
my %VOWEL_TO_UINT = do { |
32
|
|
|
|
|
|
|
my $i = 0; |
33
|
|
|
|
|
|
|
map { $_ => $i++ } @UINT_TO_VOWEL; |
34
|
|
|
|
|
|
|
}; |
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
sub _uint16_to_chunk { |
37
|
58
|
|
33
|
58
|
|
118
|
my $in = shift // Carp::croak 'usage: _uint16_to_chunk($INTEGER)'; |
38
|
58
|
|
|
|
|
83
|
my $out = ''; |
39
|
|
|
|
|
|
|
|
40
|
58
|
|
|
|
|
128
|
foreach my $i ( 1 .. $CHARS_PER_CHUNK ) { |
41
|
290
|
100
|
|
|
|
386
|
if ( $i & 1 ) { |
42
|
174
|
|
|
|
|
247
|
$out .= $UINT_TO_CONSONANT[ $in & $MASK_LAST4 ]; |
43
|
174
|
|
|
|
|
215
|
$in >>= 4; |
44
|
|
|
|
|
|
|
} |
45
|
|
|
|
|
|
|
else { |
46
|
116
|
|
|
|
|
169
|
$out .= $UINT_TO_VOWEL[ $in & $MASK_LAST2 ]; |
47
|
116
|
|
|
|
|
132
|
$in >>= 2; |
48
|
|
|
|
|
|
|
} |
49
|
|
|
|
|
|
|
} |
50
|
58
|
|
|
|
|
281
|
scalar reverse $out; |
51
|
|
|
|
|
|
|
} |
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
sub _chunk_to_uint16 { |
54
|
58
|
|
33
|
58
|
|
127
|
my $in = shift // Carp::croak 'usage: _chunk_to_uint16($INTEGER)'; |
55
|
|
|
|
|
|
|
|
56
|
58
|
50
|
|
|
|
107
|
Carp::croak 'invalid chunk: ' . $in unless length($in) == $CHARS_PER_CHUNK; |
57
|
|
|
|
|
|
|
|
58
|
58
|
|
|
|
|
69
|
my $res = 0; |
59
|
58
|
|
|
|
|
149
|
foreach my $c ( split //, $in ) { |
60
|
290
|
100
|
|
|
|
497
|
if ( exists $CONSONANT_TO_UINT{$c} ) { |
|
|
50
|
|
|
|
|
|
61
|
174
|
|
|
|
|
183
|
$res <<= 4; |
62
|
174
|
|
|
|
|
235
|
$res += $CONSONANT_TO_UINT{$c}; |
63
|
|
|
|
|
|
|
} |
64
|
|
|
|
|
|
|
elsif ( exists $VOWEL_TO_UINT{$c} ) { |
65
|
116
|
|
|
|
|
126
|
$res <<= 2; |
66
|
116
|
|
|
|
|
142
|
$res += $VOWEL_TO_UINT{$c}; |
67
|
|
|
|
|
|
|
} |
68
|
|
|
|
|
|
|
else { |
69
|
0
|
|
|
|
|
0
|
Carp::croak 'invalid quint char: ' . $c; |
70
|
|
|
|
|
|
|
} |
71
|
|
|
|
|
|
|
} |
72
|
|
|
|
|
|
|
|
73
|
58
|
|
|
|
|
249
|
$res; |
74
|
|
|
|
|
|
|
} |
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
# uint2proquint(0x7f000001) eq 'lusab-babad'; |
77
|
|
|
|
|
|
|
sub uint2proquint { |
78
|
2
|
|
33
|
2
|
0
|
8273
|
my $in = shift // Carp::croak 'usage: uint2proquint($INTEGER)'; |
79
|
2
|
|
33
|
|
|
14
|
my $sep = shift // $SEPARATOR; |
80
|
|
|
|
|
|
|
|
81
|
2
|
50
|
33
|
|
|
11
|
Carp::croak('input out of range 0-0xFFFFFFFF') |
82
|
|
|
|
|
|
|
if $in < 0 or $in > 0xffffffff; |
83
|
|
|
|
|
|
|
|
84
|
2
|
|
|
|
|
10
|
_uint16_to_chunk( $in >> 16 ) . $sep . _uint16_to_chunk($in); |
85
|
|
|
|
|
|
|
} |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
# proquint2uint('lusab-babad') == 0x7f000001; |
88
|
|
|
|
|
|
|
sub proquint2uint { |
89
|
2
|
|
33
|
2
|
0
|
10
|
my $in = shift // Carp::croak 'usage: proquint2uint($QUINT)'; |
90
|
2
|
|
33
|
|
|
10
|
my $sep = shift // $SEPARATOR; |
91
|
|
|
|
|
|
|
|
92
|
2
|
|
|
|
|
32
|
$in =~ s/$sep//g; |
93
|
2
|
50
|
|
|
|
12
|
Carp::croak 'invalid quint: ' . $in |
94
|
|
|
|
|
|
|
unless not length($in) % $CHARS_PER_CHUNK; |
95
|
|
|
|
|
|
|
|
96
|
2
|
|
|
|
|
28
|
my @chunks = $in =~ m/(.{$CHARS_PER_CHUNK})/gx; |
97
|
2
|
50
|
|
|
|
17
|
Carp::croak 'invalid quint: ' . $in unless @chunks == 2; |
98
|
|
|
|
|
|
|
|
99
|
2
|
|
|
|
|
10
|
my $out = _chunk_to_uint16( $chunks[0] ); |
100
|
2
|
|
|
|
|
5
|
$out <<= 16; |
101
|
2
|
|
|
|
|
5
|
$out += _chunk_to_uint16( $chunks[1] ); |
102
|
2
|
|
|
|
|
12
|
$out; |
103
|
|
|
|
|
|
|
} |
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
# hex2proquint('7f00001') eq 'lusab-babad' |
106
|
|
|
|
|
|
|
sub hex2proquint { |
107
|
6
|
|
33
|
6
|
0
|
10748
|
my $in = shift // Carp::croak 'usage: hex2proquint($HEXIDECIMAL)'; |
108
|
6
|
|
33
|
|
|
34
|
my $sep = shift // $SEPARATOR; |
109
|
|
|
|
|
|
|
|
110
|
6
|
|
|
|
|
25
|
$in =~ s/^0[xX]//; |
111
|
|
|
|
|
|
|
|
112
|
6
|
50
|
|
|
|
25
|
Carp::croak 'input must be multiple of 4-characters' |
113
|
|
|
|
|
|
|
unless not length($in) % 4; |
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
join( $sep, |
116
|
6
|
|
|
|
|
45
|
map { _uint16_to_chunk( hex( '0x' . $_ ) ) } $in =~ m/(.{4})/g ); |
|
12
|
|
|
|
|
50
|
|
117
|
|
|
|
|
|
|
} |
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
# proquint2hex('lusab-babad') eq '7f000001'; |
120
|
|
|
|
|
|
|
sub proquint2hex { |
121
|
6
|
|
33
|
6
|
0
|
20
|
my $in = shift // Carp::croak 'usage: proquint2hex($QUINT)'; |
122
|
6
|
|
33
|
|
|
24
|
my $sep = shift // $SEPARATOR; |
123
|
|
|
|
|
|
|
|
124
|
6
|
|
|
|
|
49
|
$in =~ s/$sep//g; |
125
|
6
|
50
|
|
|
|
36
|
Carp::croak 'invalid quint: ' . $in |
126
|
|
|
|
|
|
|
unless not length($in) % $CHARS_PER_CHUNK; |
127
|
|
|
|
|
|
|
|
128
|
6
|
|
|
|
|
52
|
my @chunks = $in =~ m/(.{$CHARS_PER_CHUNK})/g; |
129
|
6
|
50
|
|
|
|
24
|
Carp::croak 'invalid quint: ' . $in unless @chunks; |
130
|
|
|
|
|
|
|
|
131
|
6
|
|
|
|
|
17
|
join( '', map { sprintf( '%04x', _chunk_to_uint16($_) ) } @chunks ); |
|
12
|
|
|
|
|
27
|
|
132
|
|
|
|
|
|
|
} |
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
# ip2proquint('127.0.0.1') eq 'lusab-babad' |
135
|
|
|
|
|
|
|
sub ip2proquint { |
136
|
15
|
|
33
|
15
|
0
|
26468
|
my $in = shift // Carp::croak 'usage: ip2proquint($ADDRESS)'; |
137
|
15
|
|
33
|
|
|
69
|
my $sep = shift // $SEPARATOR; |
138
|
|
|
|
|
|
|
|
139
|
15
|
|
66
|
|
|
171
|
my $ip = inet_pton( AF_INET6, $in ) // inet_pton( AF_INET, $in ) |
|
|
|
33
|
|
|
|
|
140
|
|
|
|
|
|
|
// Carp::croak sprintf q{invalid IP address '%s'}, $in; |
141
|
|
|
|
|
|
|
|
142
|
15
|
|
|
|
|
104
|
join( $sep, map { _uint16_to_chunk($_) } unpack 'n*', $ip ); |
|
42
|
|
|
|
|
78
|
|
143
|
|
|
|
|
|
|
} |
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
# proquint2ip('lusab-babad') eq '127.0.0.1' |
146
|
|
|
|
|
|
|
sub proquint2ip { |
147
|
15
|
|
33
|
15
|
0
|
49
|
my $in = shift // Carp::croak 'usage: proquint2ip($ADDRESS)'; |
148
|
15
|
|
33
|
|
|
55
|
my $sep = shift // $SEPARATOR; |
149
|
|
|
|
|
|
|
|
150
|
15
|
|
|
|
|
111
|
$in =~ s/$sep//g; |
151
|
15
|
50
|
|
|
|
59
|
Carp::croak 'invalid quint: ' . $in |
152
|
|
|
|
|
|
|
unless not length($in) % $CHARS_PER_CHUNK; |
153
|
|
|
|
|
|
|
|
154
|
15
|
|
|
|
|
123
|
my @chunks = $in =~ m/(.{$CHARS_PER_CHUNK})/g; |
155
|
15
|
50
|
|
|
|
44
|
Carp::croak 'invalid quint: ' . $in unless @chunks; |
156
|
|
|
|
|
|
|
|
157
|
15
|
|
|
|
|
32
|
my $ip = pack 'n*', map { _chunk_to_uint16($_) } @chunks; |
|
42
|
|
|
|
|
69
|
|
158
|
15
|
100
|
|
|
|
154
|
return inet_ntop( 2 == @chunks ? AF_INET : AF_INET6, $ip ); |
159
|
|
|
|
|
|
|
} |
160
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
1; |
162
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
__END__ |