File Coverage

blib/lib/Text/Quote.pm
Criterion Covered Total %
statement 247 255 96.8
branch 99 134 73.8
condition 27 37 72.9
subroutine 30 32 93.7
pod 11 11 100.0
total 414 469 88.2


line stmt bran cond sub pod time code
1             package Text::Quote;
2             $Text::Quote::VERSION = '0.33';
3 1     1   75135 use 5.006;
  1         3  
4 1     1   6 use strict;
  1         4  
  1         39  
5 1     1   6 use warnings;
  1         5  
  1         27  
6 1     1   695 use Compress::Zlib;
  1         67742  
  1         216  
7 1     1   539 use MIME::Base64;
  1         693  
  1         52  
8 1     1   7 use Carp();
  1         2  
  1         17  
9 1     1   546 use Carp::Assert;
  1         1267  
  1         22  
10 1     1   124 use warnings::register;
  1         3  
  1         2463  
11              
12              
13             =head1 NAME
14              
15             Text::Quote - Quotes strings as required for perl to eval them back correctly
16              
17             =head1 SYNOPSIS
18              
19             use Text::Quote;
20              
21             my @quotes=map{$quoter->quote($_,indent=>6,col_width=>60)}('
22             "The time has come"
23             the walrus said,
24             "to speak of many things..."
25             ',"\0\1\2\3\4\5\6\a\b\t\n\13\f\r\16\17\20\21\22\23\24\25\26\27\30\31\32\e\34\35\36\37",
26             ("\6\a\b\t\n\13\f\r\32\e\34" x 5),2/3,10,'00');
27             for my $i (1..@quotes) {
28             print "\$var$i=".$quotes[$i-1].";\n";
29             }
30              
31             Would produce:
32              
33             $var1=qq'"The time has come"\n\tthe\twalrus said,\n\t"to speak of man'.
34             qq'y things..."';
35             $var2="\0\1\2\3\4\5\6\a\b\t\n\13\f\r\16\17\20\21\22\23\24\25\26\27".
36             "\30\31\32\e\34\35\36\37";
37             $var3=("\6\a\b\t\n\13\f\r\32\e\34" x 5);
38             $var4=0.666666666666667;
39             $var5=10;
40             $var6='00';
41              
42              
43             =head1 DESCRIPTION
44              
45             Text::Quote is intended as a utility class for other classes that need to be able
46             to produce valid perl quoted strings. It posses routines to determine the ideal quote
47             character to correctly quote hash keys, to correctly quote and encode binary strings.
48              
49             This code was inspired by an analysis of L by Gisle Aas.
50             In some cases it was much more than inspired. :-)
51              
52             =head1 METHODS
53              
54             =cut
55              
56             # This code derives from a number of sources
57             # 1. Data::Dump by Gisle Aas
58             # 2. MIME::Base64 by Gisle Aas
59             # Its primary intention is to isolate out the basic functionality
60             # of correctly, succintly and neatly quoting a non reference
61             # scalar variable.
62             #
63             # In this context "quoting" has a looser definition than the standard
64             # perl idea. A string is considered by this module to be correctly
65             # quoted IFF the result of _evaling_ the resultant "quoted" text produces
66             # the exact same string.
67             # ie:
68             # my $quoted=Text::Quote->quote($string);
69             # my $result=eval($string);
70             # print "Text::Quote ",($string eq $result) ? "works!" : "sucks! :(","\n";
71             #
72             ##
73             sub _stamp {
74 126     126   175 my $i = 1;
75 126         215 my @list = ('----');
76 126         776 while ( my ( $package, $filename, $line, $subroutine ) = caller($i) ) {
77 246         550 push @list, "($i) $subroutine";
78 246         921 $i++;
79             }
80              
81             #warn $subroutine."\n";
82             #warn join ( "\n", @list ), "\n";
83             }
84              
85              
86              
87              
88              
89              
90              
91              
92             # adds the method call and quoting symbols around a block of text.
93             sub _textquote_format_method {
94 3     3   9 my ( $self, $method, $str, %opts ) = @_;
95              
96 3 100       11 $method .= '(' . ( ( $method eq "pack" ) ? "'H*'," : "" );
97 3 100 33     19 $method = ( ref($self) || $self ) . "->" . $method
98             unless $method =~ /^pack/;
99 3         7 $opts{leading} = length($method);
100             #$opts{indent} += 2;
101 3         11 return $method . $self->quote_simple( $str, %opts, is_encoded => 1 ) . ")";
102              
103             }
104              
105             sub _textquote_compress {
106 1     1   5 my ( $self, $str, %opts ) = @_;
107 1 50       4 return unless $str;
108 1         4 my $method = "";
109 1         6 ( $method, $str ) = $self->_textquote_encode64( Compress::Zlib::compress($str), %opts );
110 1         4 $method = "decompress64";
111 1 50       8 return wantarray ? ( $method, $str ) : $self->_textquote_format_method( $method, $str, %opts );
112             }
113              
114             # Encodes a string in base64
115             sub _textquote_encode64 {
116 2     2   792 my ( $self, $str, %opts ) = @_;
117 2         63 $str = MIME::Base64::encode( $str, "" );
118             return
119             wantarray
120 2 50       14 ? ( "decode64", $str )
121             : $self->_textquote_format_method( "decode64", $str, %opts );
122             }
123              
124              
125             #
126             # _textquote_encode
127             # Encodes a string, either by compression or by pack
128             #
129             sub _textquote_encode {
130              
131 2     2   8 my ( $self, $str, %opts ) = @_;
132              
133 2         5 $self->_stamp;
134 2         4 my $method;
135             my $encoded;
136 2 50       7 my $encode_at =defined($opts{encode_at})?$opts{encode_at}:$self->quote_prop("encode_at");
137 2 100       8 if ( length($str)*2 > $encode_at ) {
138 1         5 ( $method, $encoded ) = $self->_textquote_encode64( $str, %opts );
139             } else {
140 1         2 $method = "pack";
141 1         7 $encoded = unpack( "H*", $str );
142             }
143              
144             return (wantarray)
145 2 50       9 ? ( $method, $encoded )
146             : $self->_textquote_format_method( $method, $encoded, %opts );
147             }
148              
149             #
150             # Tries to find a repeated pattern in the text
151             #
152             sub _textquote_pattern { #not a pattern, really a multiple
153 7     7   11 my $self = shift;
154              
155 7         21 $self->_stamp;
156 7         14 local $_ = shift;
157 7 50       15 return unless $_;
158 7         16 my %opts = @_;
159              
160 7 50       20 return if $opts{no_repeat};
161              
162             # Check for repeated string
163 7 50       21 my $rl = ( exists( $opts{repeat_len} ) ) ? $opts{repeat_len} : $self->quote_prop("repeat_len");
164              
165 7 100       88 if (/\A(.{1,$rl}?)(\1*)\z/s) {
166              
167 2         7 my $base = $self->quote_simple($1);
168              
169 2         12 my $repeat = length($2) / length($1) + 1;
170              
171 2         11 return "($base x $repeat)";
172             }
173              
174 5         16 return;
175             }
176              
177              
178             #
179             # Escapes a string
180             # takes the string, the type of quote (qq or q) and the symbol used
181             #
182             sub _textquote_escaped {
183 18     18   29 my $self = shift;
184              
185 18         63 $self->_stamp;
186 18         43 local $_ = ( my $str = shift );
187 18         24 my $type = shift;
188 18         23 my $qsymb = shift;
189              
190             # Now we need to escape our quote char in string.
191 18         129 ( my $escaped = $qsymb ) =~ s/(.)/\\$1/g;
192              
193             #and escape variables and our quote chars
194 18 100       40 if ( "qq" eq $type ) {
195 6         57 s/([$escaped\\\@\$])/\\$1/g;
196             } else { # dont have to escape variables
197 12         54 s/([$escaped\\])/\\$1/g;
198             }
199              
200             # fast exit for straight chars
201 18 50       42 if ($self->quote_prop("encode_high")) {
202 0 0       0 return ($_) unless /[^\t\040-\176]/;
203             } else {
204 18 100       89 return ($_) unless /[^\t\040-\377]/;
205             }
206              
207 6         12 my $esc_class = $self->quote_prop("esc_class");
208 6         20 my $esc_chars = $self->quote_prop("esc_chars");
209 6         81 s/($esc_class)/$esc_chars->{$1}/g; # escape interpolatable symbols
210              
211             # octal escapes -- harder to read but shorter
212             # no need for 3 digits in escape for these
213 6         36 s/([\0-\037])(?!\d)/'\\'.sprintf('%o',ord($1))/eg;
  129         356  
214              
215             # still go for the low ones cause there could be a digit following,
216             # either way use 3 digits
217 6         20 s/([\0-\037\177-\377])/'\\'.sprintf('%03o',ord($1))/eg;
  129         307  
218              
219 6         23 return $_;
220             }
221              
222             sub _textquote_number {
223              
224             #returns undef or the value of the number
225              
226 50     50   85 my ( $self, $num ) = @_;
227              
228 50 100 66     405 if ( defined $num && $num =~ /\A-?(?:0|[1-9]\d{0,8})(\.\d{0,18})?\z/ ) {
229 29         69 return $num;
230             }
231 21         42 return;
232             }
233              
234              
235              
236              
237             =head2 quote(STR,OPTS)
238              
239             Quotes a string. Will encode or compress or otherwise change the strings representation
240             as the options specify. If an option is omitted the class default is used if it exists then
241             an internal procedure default is used.
242              
243             Normal behaviour is as follows
244              
245             =over 4
246              
247             =item Numbers
248              
249             Not quoted
250              
251             =item Short Repeated Substr
252              
253             Converted into a repeat statement C<($str x $repeat)>
254              
255             =item Simple Strings
256              
257             Single quoted, or double quoted if multiline or containing small numbers of other
258             control characters (tabs excluded).
259              
260             =item Binary Strings
261              
262             Converted into hex using L or if larger into Base64 using L
263              
264             =item Large Strings
265              
266             Converted to a call to L.
267              
268             =back
269              
270             The output and OPTS will passed on to L for formatting if it
271             is multiline. No indentation of the first line is done.
272              
273             See L for options.
274              
275             =cut
276              
277              
278             sub quote {
279              
280             # Main routine, the essence of this is that a returns back a quoted construct
281             # it calls all the others as it needs/or can depending on the size of the string,
282             # the type of data it contains and any options passed.This can include reducing the
283             # the string to a ("ABC" x $count) or conterting it to a different format, such as
284             # hex or base64, or even compressing it.
285 41     41 1 4287 my $self = shift->_self_obj;
286 41         77 my $str = shift(@_);
287              
288 41         95 $self->_stamp;
289              
290              
291 41 100       109 return 'undef' unless defined $str;
292 40         218 $str="".$str;
293              
294 40 50       144 Carp::croak "cant use odd number of parameters:" . scalar(@_)
295             unless @_ % 2 == 0;
296 40         78 my %opts = @_;
297              
298             my $compress_at =
299 40 50       129 defined( $opts{compress_at} ) ? $opts{compress_at} : $self->quote_prop("compress_at");
300 40 50       96 my $encode_at = defined( $opts{encode_at} ) ? $opts{encode_at} : $self->quote_prop("encode_at");
301             my $repeat_at =
302 40 50       94 defined( $opts{repeat_at} ) ? $opts{repeat_at} : $self->quote_prop("repeat_at");
303              
304 40         79 my $ret = $self->_textquote_number($str);
305 40 100       260 return $ret if defined $ret;
306              
307 11   100     40 $opts{indent} ||= 0;
308              
309 11 100 66     41 if ( $compress_at && length($str) > $compress_at ) {
310              
311 1         6 my $ret = $self->_textquote_compress( $str, %opts );
312              
313 1 50       9 $opts{reqs}->{__PACKAGE__}++ if $opts{reqs};
314              
315 1 50       8 return $ret if $ret;
316             }
317              
318 10 100 66     31 if ( $repeat_at && length($str) > $repeat_at ) {
319              
320 7         25 my $ret = $self->_textquote_pattern( $str, %opts );
321 7 100       25 return $ret if defined $ret;
322              
323             }
324              
325 8         24 my ( $qq, $qb, $qe, $nqq ) = $self->best_quotes( $str, %opts );
326 8         29 my $escaped = $self->_textquote_escaped( $str, $qq, $qb . $qe );
327              
328 8 100 66     40 if ( $encode_at
      66        
329             && ( length($escaped) > $encode_at
330             && length($escaped) > ( length($str) * 2 ) ) )
331             {
332              
333             # too much binary data, better to represent as a hex string?
334             # Base64 is more compact than hex when string is longer than
335             # 17 bytes (not counting any require statement needed).
336             # But on the other hand, hex is much more readable.
337 2         8 my ( $method, $str ) = $self->_textquote_encode( $str, %opts );
338 2 50 66     12 $opts{reqs}->{__PACKAGE__}++ if $method && $method ne "pack" && $opts{reqs};
      66        
339 2 50       9 return $self->_textquote_format_method( $method, $str, %opts ) if $method;
340             }
341              
342 6 100       25 return $self->quote_columns( $escaped, ( $nqq ? $qq . $qb : $qb ), $qe, %opts );
343              
344             }
345              
346              
347             =head2 quote_simple(STR,OPTS)
348              
349             Quotes a string. Does not attempt to encode it, otherwise the same L
350              
351             =cut
352              
353             sub quote_simple {
354 10     10 1 20 my $self = shift(@_);
355 10         22 my $str = "".shift(@_);
356 10         20 my %opts = @_;
357              
358 10         23 $self->_stamp;
359 10         24 my $ret = $self->_textquote_number($str);
360 10 50       20 return $ret if $ret;
361             my ( $qq, $qb, $qe, $nqq ) =
362 10 100       32 ( $opts{is_encoded} ? ( 'q', "'", "'", 0 ) : $self->best_quotes( $str, %opts ) );
363 10         34 my $escaped = $self->_textquote_escaped( $str, $qq, $qb . $qe );
364 10 50       43 return $self->quote_columns( $escaped, ( $nqq ? $qq . $qb : $qe ), $qe, %opts );
365             }
366              
367             =head2 quote_key(STR,OPTS)
368              
369             Quotes a string as though it was a hash key. In otherwords will only quote it
370             if it contains whitespace, funky characters or reserved words.
371              
372             See L for options.
373              
374             =cut
375              
376              
377             sub quote_key {
378 12     12 1 30 my $self = shift(@_);
379 12         24 my $key = "".shift(@_);
380 12         21 my %opts = @_;
381 12         27 $self->_stamp;
382              
383             #$key="$key";
384 12         28 my $rule=$self->quote_prop("key_quote");
385 12 50       27 return "''" if $key eq "";
386 12 100       30 unless ($rule) {
    100          
387 1         5 return $key;
388 0         0 } elsif ($rule eq 'auto') {
389 10 100 66     66 if ( $key =~ /\A(?:-[A-Za-z]+\w*|[_A-Za-z]+\w*|\d+)\z/ && !$self->quote_prop("key_quote_hash")->{$key} ) {
390 6         35 return $key;
391             } else {
392 4         12 return $self->quote_simple( $key, %opts );
393             }
394             } else {
395 1         6 return $self->quote_simple( $key, %opts );
396             }
397             }
398              
399             =head2 quote_regexp(STR)
400              
401             Quotes a regexp or string as though it was a regexp, includes the qr operator.
402             Will automatically select the appropriate quoting char.
403              
404             =cut
405              
406             sub quote_regexp {
407 1     1 1 3 my $self = shift;
408 1         4 my $rex = "".shift(@_);
409              
410             # a stringified regex will look like (?-xism: ... )
411             # when it was created by an optionless //
412             # this means that if we do bf_dump(eval(bf_dump(qr/.../)))
413             # we dont get the same regex (it will be nested again)
414             # so we strip the added layer off if it is (?-xism:
415             # note this means the regexp is safe:had there been any options
416             # the prefix would be different and we would ignore it.
417 1 50       14 if ( substr( $rex, 0, 8 ) eq "(?-xism:" ) {
418 0         0 $rex = substr( $rex, 8, length($rex) - 9 );
419             }
420              
421             # find the ideal quote symbol for the regex
422 1         7 my ( $qq, $qb, $qe, $nqq ) = $self->best_quotes( $rex, chars => [qw( / ! {} - & ; )] );
423 1         4 my $qs = quotemeta $qb . $qe;
424              
425             # escape any quote symbols in the regex, ideally there shouldnt
426             # be any because of _quote_best
427 1         17 $rex =~ s/([$qs])/\\$1/g;
428 1         9 return "qr$qb$rex$qe";
429             }
430              
431             =head2 quote_columns(STR,QB,QE,OPTS)
432              
433             Takes a preescaped string and chops it into lines with a specific maximum length
434             each line is independantly quoted and concatenated together, this allows the column
435             to be set at a precise indent and maximum width. It also handles slicing the string
436             at awkward points, such as in an escape sequence that might invalidate the quote.
437             Note the first line is not indented by default.
438              
439             STR is the string to quote. QB is the begin quote pattern. QE is end quote pattern.
440             OPTS can be
441              
442             col_width (defaults 76) Width of text excl. quote symbols and cat char
443             leading (defaults 0) Width of first line offset.
444             indent (defaults 0) Width of overall indentation
445             indent_first (defaults 0) Whether the first line is indented.
446              
447             =cut
448              
449              
450             sub quote_columns {
451 16     16 1 36 my $self=shift;
452 16         36 my $str="".shift(@_);
453 16         38 my ($qb, $qe, %opts ) = @_;
454              
455 16         34 $self->_stamp;
456 16         20 my @rows;
457 16         26 my $line = "";
458 16         21 my $pos = 0;
459 16   100     56 my $width = $opts{col_width} || 76;
460 16   100     49 my $lead = $opts{leading} || 0;
461 16   100     38 my $indent = $opts{indent} || 0;
462              
463             #$lead -= 2 if $lead > 2; #???
464 16         23 my $len = $width - $lead;
465 16         534 while ( $str =~ /\G([^\\]{1,$len}|\\\d{1,3}|\\.)/gs ) {
466              
467              
468 124 100       460 if ( length($line) + length($1) > $width - $lead ) {
469 16         34 push @rows, $line;
470 16 100       30 $lead = 0 if ($lead);
471 16         21 $line = "";
472             }
473 124         230 $line .= $1;
474 124   100     295 $len = $width - $lead - length($line) || 1;
475 124         2600 $pos = pos($str);
476              
477             #warn "$pos $len $line\n";
478             }
479 16 50       57 push @rows, $line if $line;
480 16 50       65 die "pos:" . $pos . "\n" . substr( $str, $pos ) . "\n"
481             if $pos != length($str);
482              
483             #print $str;
484 16         181 return $qb . join ( $qe . ".\n" . ( " " x $indent ) . $qb, @rows ) . $qe;
485             }
486              
487              
488              
489             =head2 decompress64(STR)
490              
491             Takes a compressed string in quoted 64 representation and decompresses it.
492              
493             =cut
494              
495             # takes a compressed quoted64 string and dequotes it
496             sub decompress64 {
497 0     0 1 0 my ( $self, $str ) = @_;
498 0         0 return Compress::Zlib::uncompress( $self->decode64($str) );
499             }
500              
501             =head2 decode64(STR)
502              
503             Takes a string encoded in base 64 and decodes it.
504              
505             =cut
506              
507             # takes a quoted64 string and dequotes it
508             sub decode64 {
509 0     0 1 0 my ( $self, $str ) = @_;
510 0         0 return MIME::Base64::decode($str);
511             }
512              
513             =head2 best_quotes(STR,OPTS)
514              
515             Selects the optimal quoting character and quoting type for a given string.
516              
517             Returns a list
518              
519             $qq - Either 'q' or 'qq'
520             $qbegin - The beginning quote character
521             $qend - The ending quote character
522             $needs_type - Whether $qq is needed to make the quotes valid.
523              
524             OPTS may include the normal options as well as
525              
526             chars : a list of chars (or pairs) to be allowed for quoting.
527              
528             =cut
529              
530             sub best_quotes {
531              
532             # is capable of deciding if something should be single
533             # quoted, or double quoted and which quote character to
534             # use.
535             # A string may be single quoted if it contains no control
536             # characters or line breaks.
537             # returns ( $qsym, $qq, $qbegin, $qend,$fqbegin )
538             # needs a complete rework
539 18     18 1 1444 my $self = shift;
540              
541 18         41 $self->_stamp;
542 18         42 local $_ = "".shift(@_);
543 18         36 my %opts = @_;
544              
545 18 50       36 warnings::warnif("Undef passed at _textquote_best") unless defined($_);
546 18 50       37 warnings::warnif("Reference passed at _textquote_best") if ref $_;
547              
548             # Use double quotes if we have non tab control chars or high bit chars
549             # (\n included)
550             my $qq = exists( $opts{use_qq} ) ? $opts{use_qq} :
551 18 50       47 $self->quote_prop('encode_high') ? /[^\t\040-\176]/ : /[^\t\040-\377]/;
    50          
552              
553 18         31 my @chars; # chars we can use for quoting with
554 18 100       33 if ( $opts{chars} ) { # Did they supply a list of choices?
555 1         3 @chars = @{ $opts{chars} }; # use them
  1         3  
556             } else { # Use the defaults
557 17         25 @chars = @{ $self->quote_prop("quote_chars") };
  17         29  
558 17 100       61 unshift @chars, ($qq) ? qw( " ' ) : qw( ' " );
559             }
560              
561             #print "Using @chars\n";
562 18         37 my $char_class = "[" . join ( "", map { quotemeta } @chars ) . "]";
  227         378  
563 18         50 my %counts;
564 18         109 @counts{@chars} = (0) x @chars;
565              
566 18         284 $counts{$1}++ while /($char_class)/g;
567              
568             {
569 1     1   9 no warnings;
  1         2  
  1         643  
  18         32  
570 18 50       62 $counts{'{}'} = $counts{'{'} + $counts{'}'} if exists $counts{'{}'};
571 18 100       46 $counts{'[]'} = $counts{'['} + $counts{']'} if exists $counts{'[]'};
572 18 100       43 $counts{'()'} = $counts{'('} + $counts{')'} if exists $counts{'()'};
573 18 50       38 $counts{'<>'} = $counts{'<'} + $counts{'>'} if exists $counts{'<>'};
574             }
575 18         72 delete $counts{$_} foreach qw' { } [ ] ( ) < >';
576              
577 18         31 my $qsym = shift @chars;
578 18         31 my $low = $counts{$qsym};
579 18         26 my $lowsym = $qsym;
580 18         45 while ( $low > 0 ) {
581 16 100       26 last unless @chars;
582 15         22 $qsym = shift @chars;
583 15 100       34 if ($counts{$qsym} < $low) {
584 2         4 $low = $counts{$qsym};
585 2         5 $lowsym=$qsym;
586             }
587             }
588 18         24 $qsym=$lowsym;
589              
590 18         36 my $qbegin = substr( $qsym, 0, 1 );
591 18         24 my $qend = substr( $qsym, -1, 1 );
592 18         25 my $needs_type;
593 18 100       40 if ($qq) {
594 6         9 $qq = 'qq';
595 6 100       13 $needs_type = $qbegin eq '"' ? 0 : 1;
596             } else {
597 12         22 $qq = 'q';
598 12 100       24 $needs_type = $qbegin eq "'" ? 0 : 1;
599             }
600              
601 18         112 return ( $qq, $qbegin, $qend, $needs_type );
602             }
603              
604             =head1 OVERIDE METHODS
605              
606             These methods are defined by Text::Quote for when it runs as a stand alone.
607             Normally they would be overriden by child classes, or alternatively used by
608             the child class.
609              
610             =cut
611              
612 0         0 BEGIN {
613              
614             # things we need to escape
615             #from G.A.
616              
617 1     1   19 my %esc_chars = (
618             "\a" => "\\a",
619             "\b" => "\\b",
620             "\t" => "\\t",
621             "\n" => "\\n",
622             "\f" => "\\f",
623             "\r" => "\\r",
624             "\e" => "\\e",
625             );
626              
627 1         12 my %known_keywords = map { $_ => 1 }
  249         836  
628             qw( __FILE__ __LINE__ __PACKAGE__ __DATA__ __END__ AUTOLOAD BEGIN CORE
629             DESTROY END EQ GE GT INIT LE LT NE abs accept alarm and atan2 bind
630             binmode bless caller chdir chmod chomp chop chown chr chroot close
631             closedir cmp connect continue cos crypt dbmclose dbmopen defined
632             delete die do dump each else elsif endgrent endhostent endnetent
633             endprotoent endpwent endservent eof eq eval exec exists exit exp fcntl
634             fileno flock for foreach fork format formline ge getc getgrent
635             getgrgid getgrnam gethostbyaddr gethostbyname gethostent getlogin
636             getnetbyaddr getnetbyname getnetent getpeername getpgrp getppid
637             getpriority getprotobyname getprotobynumber getprotoent getpwent
638             getpwnam getpwuid getservbyname getservbyport getservent getsockname
639             getsockopt glob gmtime goto grep gt hex if index int ioctl join keys
640             kill last lc lcfirst le length link listen local localtime lock log
641             lstat lt m map mkdir msgctl msgget msgrcv msgsnd my ne next no not oct
642             open opendir or ord pack package pipe pop pos print printf prototype
643             push q qq qr quotemeta qw qx rand read readdir readline readlink
644             readpipe recv redo ref rename require reset return reverse rewinddir
645             rindex rmdir s scalar seek seekdir select semctl semget semop send
646             setgrent sethostent setnetent setpgrp setpriority setprotoent setpwent
647             setservent setsockopt shift shmctl shmget shmread shmwrite shutdown
648             sin sleep socket socketpair sort splice split sprintf sqrt srand stat
649             study sub substr symlink syscall sysopen sysread sysseek system
650             syswrite tell telldir tie tied time times tr truncate uc ucfirst umask
651             undef unless unlink unpack unshift untie until use utime values vec
652             wait waitpid wantarray warn while write x xor y);
653              
654             =head2 init()
655              
656             Takes a list of options and uses them to initialize the quoting object.
657             Defaults are provided if an option is not specified.
658              
659             esc_chars : a hash of chars needing to be escaped and their escaped equivelent
660             esc_class : a regex class that matches the chars needing to be escaped
661             quote_chars : chars to be used as alternate quote chars
662             key_quote_hash : hash of words that must be quoted if used as a hash key
663             repeat_len : Length of pattern to look for in the string
664             encode_high : Set to 1 to cause high bits chars to be escaped. Dafaults to 0
665              
666             Set the following to 0 to disable
667              
668             repeat_at : Length of string at which Text::Quote should see if there is a repeated pattern.
669             encode_at : Length at which binary data should be quoted in Base64
670             compress_at : Length at which the string should be compressed using Compress::Zlib
671              
672             These options are set using L
673              
674             =cut
675              
676             sub init {
677 2     2 1 5 my $self = shift;
678              
679 2         7 $self->_stamp;
680 2         422 my %hash = (
681             esc_chars => {%esc_chars},
682             esc_class => join ( "", "[", keys(%esc_chars), "]" ),
683              
684             #Forbidden until best_quotes is fixed :
685             quote_chars => [ qw; / ! | - . : () [] {} ;, '#', ';' ],
686             key_quote_hash => {%known_keywords},
687             key_quote => 'auto', #auto/true/false
688             repeat_len => 20, # maximum size of repeat sequence
689             repeat_at => 20, # number of chars before we even bother
690             encode_at => 160,
691             compress_at => 512, # number of chars at which we compress no matter what
692             encode_high => 0,
693             @_
694             );
695 2         53 $self->quote_prop( \%hash );
696 2         5 return \%hash;
697             }
698             }
699              
700             =head2 new()
701              
702             Creates a hash based object and calls L afterwards
703              
704             =cut
705              
706              
707             sub new {
708 2     2 1 111 my $class = shift;
709 2         7 my $self = bless {}, $class;
710 2         11 $self->init(@_);
711 2         6 return $self;
712             }
713              
714              
715             =head2 quote_prop()
716              
717             As this class is intended to be subclassed all of its parameters are kept
718             and accessed through a single accessor.
719              
720             This hash is normally stored as $obj->{Text::Quote} however should the default
721             class type not be a hash this method may be overriden to provide access to the
722             the Text::Quote proprty hash. Or even to redirect various properties elsewhere.
723              
724             Called with no parameters it returns a reference to the property hash.
725             Called with a string as the only parameter it returns the value of that named property.
726             Called with a string as the first parameter and a value it will set the property
727             to equal the value and return the new value. Called with a reference as the only parameter
728             the passed value is substituted for the property hash.
729              
730             =cut
731              
732              
733             #use Data::Dumper;
734             sub quote_prop {
735 217     217 1 868 my $self = shift->_self_obj;
736             #$self->_stamp;
737             #print Dumper($self);
738 217         293 my $pck = __PACKAGE__;
739              
740 217 50       366 return $self->{$pck} unless @_;
741              
742              
743 217         264 my $prop = shift;
744 217 100       336 if ( ref $prop ) {
745 2 50       12 Carp::croak "Expecting HASH based property bag!"
746             unless UNIVERSAL::isa( $prop, "HASH" );
747 2         10 return $self->{$pck} = $prop;
748             }
749              
750 215         624 should( ref $self->{$pck}, "HASH" ) if DEBUG;
751              
752             warnings::warnif("Property '$prop' not known")
753 215 50       998 unless exists( $self->{$pck}->{$prop} );
754              
755 215 100       377 $self->{$pck}->{$prop} = shift if @_;
756 215         452 return $self->{$pck}->{$prop};
757              
758             }
759              
760             =head2 _self_obj()
761              
762             This is a utility method to enable Text::Quote and its descendants the ability to
763             act as both CLASS and OBJECT methods. Creates an object to act as a class object.
764              
765             If called as an object method returns the object
766              
767             If called as a class method returns a singleton, which is the result of calling
768             class->new(); The singleton is inserted into the calling classes package under
769             the global scalar $class::SINGLETON and is reused thereafter. The object is kept in
770             a closure for maximum privacy of the object data.
771              
772             =cut
773              
774              
775             sub _self_obj {
776 258 100   258   554 ref( $_[0] ) && return $_[0];
777 1     1   8 no strict 'refs';
  1         2  
  1         157  
778             #closure to keep singleton private from prying dumpers.
779             #thank dan brook.
780 7 100       10 unless (${ $_[0] . '::SINGLETON' }) {
  7         29  
781 1         15 my $obj=$_[0]->new();
782 1 50   7   6 my $sub=sub{$obj=shift if @_; $obj};
  7         16  
  7         12  
783 1         3 ${ $_[0] . '::SINGLETON' } = $sub;
  1         5  
784             }
785 7         12 return ${ $_[0] . '::SINGLETON' }->();
  7         16  
786             }
787              
788             #print __PACKAGE__->quote([]);
789             #/|'"-,!([{#;.:
790              
791             #exit;
792              
793             =head1 INTENTION
794              
795             I wrote this module to enable me to avoid having to put code for how to neatly output perl quoted
796             strings in a reasonable way in the same module as L. I've documented
797             it and packaged in the mind that others may find it useful, and or help me improve it. I was thinking
798             for example that there are a number of modules with one form of quoting or another, be it SQL
799             statements or excel CSV quoting. There are lots of modules (and ways) of reading these formats
800             but no one clear location for finding ones that output them. Perhaps they could live here?
801             Feedback welcome.
802              
803             =head1 TODO
804              
805             Better synopsis. Better Description. More tests.
806              
807             =head1 EXPORTS
808              
809             None.
810              
811             =head1 REPOSITORY
812              
813             L
814              
815             =head1 AUTHOR
816              
817             Yves Orton, Edemerphq@hotmail.comE
818              
819             Parts by Gisle Aas
820              
821             Additional testing and encouragement Dan Brook
822              
823             =head1 CAVEAT
824              
825             This module is currently in B condition. It should not be used in a
826             production enviornment, and is released with no warranty of any kind whatsoever.
827              
828             Corrections, suggestions, bugreports and tests are welcome!
829              
830             =head1 SEE ALSO
831              
832             L.
833              
834             =head1 COPYRIGHT AND LICENSE
835              
836             This software is copyright (c) 2002 by Yves Orton .
837              
838             This is free software; you can redistribute it and/or modify it under
839             the same terms as the Perl 5 programming language system itself.
840              
841             =cut
842              
843             1;