File Coverage

blib/lib/Scalar/Quote.pm
Criterion Covered Total %
statement 54 79 68.3
branch 21 42 50.0
condition n/a
subroutine 12 14 85.7
pod 6 8 75.0
total 93 143 65.0


line stmt bran cond sub pod time code
1             package Scalar::Quote;
2              
3             our $VERSION = '0.26';
4              
5 1     1   40333 use 5.006;
  1         3  
  1         37  
6 1     1   7 use strict;
  1         1  
  1         33  
7 1     1   5 use warnings;
  1         5  
  1         7979  
8              
9             require Exporter;
10             our @ISA = qw(Exporter);
11              
12             our %EXPORT_TAGS = ( 'quote' => [ qw( quote quote_number quote_cut quote_start ) ],
13             'diff' => [ qw( str_diff str_diffix ) ],
14             'short' => [ qw( Q N S D ) ] );
15             our @EXPORT_OK = (@{$EXPORT_TAGS{quote}},
16             @{$EXPORT_TAGS{diff}},
17             @{$EXPORT_TAGS{short}});
18             our @EXPORT = qw();
19              
20             # converts a char to its hex representation
21             sub char_to_hex ($ ) {
22 51253     51253 0 54796 my $c=ord(shift);
23 51253 50       241594 sprintf( ($c < 256 ? '\x%02x' : '\x{%x}'), $c);
24             }
25              
26             my %esc = ( "\n" => '\n',
27             "\t" => '\t',
28             "\r" => '\r',
29             "\\" => '\\\\',
30             "\a" => '\a',
31             "\b" => '\b',
32             "\f" => '\f' );
33              
34             sub escape_char($ ) {
35 54755     54755 0 77566 my $char=shift;
36 54755 100       129801 exists $esc{$char} ? $esc{$char} : char_to_hex($char)
37             }
38              
39             # converts unprintable chars to \x{XX} and also escapes '"' and '\' if
40             # required
41             sub Q ($ ) {
42 350     350 1 119188 my $s=shift;
43 350 50       833 defined $s or return 'undef';
44 350 50       1885 if ($s=~s/([^!#&()*+,\-.\/0123456789:;<=>?ABCDEFGHIJKLMNOPQRSTUVWXYZ\[\]\^_`abcdefghijklmnopqrstuvwxyz{|}~ ])/escape_char($1)/ge) {
  54755         94947  
45 350         2823 return qq("$s");
46             }
47 0         0 return qq('$s');
48             }
49             *quote=\&Q;
50              
51             # compares two strings and returns the position where they start to be
52             # diferent, i.e diffix('good morning', 'good afternoon') == 5
53              
54             sub str_diffix ($$) {
55 202     202 1 1536 my ($a, $b)=@_;
56              
57 202 50       3228 $a='' unless defined $a;
58 202 50       536 $b='' unless defined $b;
59              
60 202 50       414 return -1 if $a eq $b;
61              
62             # my $c;
63             # for (my $i=0;;$i++) {
64             # $c=substr($a,$i,1);
65             # return $i
66             # unless ( $c ne '' and $c eq substr($b,$i,1));
67             # }
68              
69 202         286 my $la = length $a;
70 202         247 my $lb = length $b;
71              
72 202 100       456 my $min = $la < $lb ? $la : $lb;
73              
74 202         1174 my $c = substr($a, 0, $min) ^ substr($b, 0, $min);
75 202 100       3330 if ($c =~ m/[^\0]/g) {
76 201         1820 return pos($c) - 1;
77             }
78 1         8 return $min;
79             }
80              
81             # quote_cut($string, $start, $len), like substr() but adds a head and a tail
82             # to the substring reported how many chars have been left alone. It
83             # also escapes the string.
84              
85             sub quote_cut ($$$ ) {
86 200 50   200 1 433 return 'undef' unless defined $_[0];
87 200         328 my (undef, $start, $len)=@_;
88 200         286 my $end=length($_[0])-$len-$start;
89 200 50       417 if ($end<0) {
90 0         0 $start+=$end;
91 0         0 $end=0;
92             }
93 200 50       409 if ($start<0) {
94 0         0 $start=0;
95             }
96 200         535 my $s=sprintf("[%d chars omitted]", $start);
97 200 50       586 if (length $s>=$start) {
98 0         0 $len+=$start;
99 0         0 $start=0;
100 0         0 $s='';
101             }
102 200         361 my $e=sprintf("[%d chars omitted]", $end);
103 200 50       367 if (length $e>=$end) {
104 0         0 $len+=$end;
105 0         0 $e='';
106             }
107 200         638 quote($s.substr($_[0], $start, $len).$e);
108             }
109              
110              
111             # escape and quote string start operator, like Q but truncates the
112             # string if it is to long.
113             sub S ($;$ ) {
114 0 0   0 1 0 my $len=defined $_[1] ? $_[1] : 32;
115 0         0 quote_cut ($_[0], 0, $len);
116             }
117             *quote_start=\&S;
118              
119             my $number_re=qr/^\s*[+-]?(?:\d+|\d*\.\d*)(?i:E[+-]?\d+)?\s*$/;
120              
121             # quote number
122             sub N ($ ) {
123 1     1   17 no warnings;
  1         2  
  1         196  
124 0 0   0 1 0 if (defined $_[0]) {
125 0 0       0 if ($_[0]=~/$number_re/o) {
126 0         0 return sprintf("%f", $_[0]);
127             }
128 0         0 return sprintf("%f (str: %s)", $_[0], S($_[0]));
129             }
130             'undef'
131 0         0 }
132             *quote_number=\&N;
133              
134             # D computes the difference between two strings.
135             sub D ($$;$$ ) {
136 1     1   6 no warnings 'uninitialized';
  1         3  
  1         149  
137 100 50   100 1 853 return () if $_[0] eq $_[1];
138              
139 100 50       333 my $len=defined $_[3] ? $_[3] : 32;
140 100 50       366 my $start=(defined $_[2] ? $_[2] : -8)
141             + str_diffix($_[0], $_[1]);
142 100         301 my $a=quote_cut($_[0], $start, $len);
143 100         413 my $b=quote_cut($_[1], $start, $len);
144              
145 100 50       844 return ($a, $b) if (wantarray);
146              
147             {
148 1     1   6 no strict 'refs';
  1         2  
  1         177  
  0            
149 0           my $caller = caller;
150 0           my $pa=$caller."::a";
151 0           my $pb=$caller."::b";
152 0           ${$pa}=$a;
  0            
153 0           ${$pb}=$b;
  0            
154             }
155 0           return 1;
156             }
157             *str_diff=\&D;
158              
159              
160              
161              
162             1;
163             __END__