File Coverage

web/cgi-bin/yatt.lib/YATT/ArgTypes.pm
Criterion Covered Total %
statement 76 81 93.8
branch 18 26 69.2
condition 2 3 66.6
subroutine 14 15 93.3
pod 0 5 0.0
total 110 130 84.6


line stmt bran cond sub pod time code
1             # -*- mode: perl; coding: utf-8 -*-
2 3     3   2814 package YATT::ArgTypes; use YATT::Inc;
  3         7  
  3         22  
3 3     3   14 use strict;
  3         6  
  3         102  
4 3     3   15 use warnings qw(FATAL all NONFATAL misc);
  3         6  
  3         137  
5              
6 3     3   20 use base qw(YATT::Class::Configurable);
  3         6  
  3         723  
7 3         25 use YATT::Fields qw(cf_callpack
8             cf_base cf_type_map cf_type_fmt
9             cf_type_name
10             cf_debug
11 3     3   522 );
  3         5  
12 3     3   15 use YATT::Util;
  3         6  
  3         440  
13 3     3   16 use YATT::Util::Symbol;
  3         7  
  3         237  
14 3     3   23 use Carp;
  3         3  
  3         2873  
15              
16             sub import {
17 3     3   9 my $pack = shift;
18 3         9 my ($callpack) = caller;
19 3         8 my @types;
20 3         13 my $opts = $pack->new(callpack => $callpack
21             , $pack->parse_args(\@_, \@types));
22 3         19 $opts->add_type($_) for @types;
23             }
24              
25             sub parse_args {
26 3     3 0 7 my ($pack, $arglist, $taskqueue) = @_;
27 3         6 my @confs;
28 3         11 while (@$arglist) {
29 33 100       118 if (ref $arglist->[0]) {
    50          
30 21         51 push @$taskqueue, shift @$arglist;
31             } elsif (my ($flag, $key) = $arglist->[0] =~ /^([\-:])(\w+)/) {
32 12         18 shift @$arglist;
33 12 100       29 my $value = $flag eq ':' ? 1 : shift @$arglist;
34 12         45 push @confs, $key, $value;
35             } else {
36 0         0 croak "Invalid option '$arglist->[0]'";
37             }
38             }
39 3         36 @confs;
40             }
41              
42             sub add_type {
43 21     21 0 38 (my MY $self, my ($desc)) = @_;
44 21         32 my $type = shift @$desc;
45 21         80 my $fullclass = sprintf $self->{cf_type_fmt}, $type;
46              
47 21         54 $self->{cf_type_map}{$type} = $fullclass;
48              
49             define_const(globref($fullclass, "type_name"), $type)
50 21 50       93 if $self->{cf_type_name};
51              
52             # t_zzz typealias.
53 21         83 define_const(globref($self->{cf_callpack}, "t_$type"), $fullclass);
54              
55 21         66 my $fields = fields_hash($self);
56              
57 21         42 my (@symbols, @tasks, %config);
58 21         55 while (@$desc) {
59 27 100       137 if (ref $desc->[0] eq 'SCALAR') {
    50          
60 9         22 my ($nameref, $value) = splice @$desc, 0, 2;
61 9         13 my $code = do {
62 9 50       19 unless (ref $value) {
    0          
63 9     0   56 sub () { $value };
  0         0  
64             } elsif (ref $value eq 'CODE') {
65 0         0 $value;
66             } else {
67 0         0 die "Unknown ArgType desc for $$nameref : '$value'";
68             }
69             };
70 9         37 push @symbols, [$$nameref, $code];
71             # *{globref($fullclass, $$nameref)} = $code;
72             } elsif (my ($flag, $key) = $desc->[0] =~ /^([\-:])(\w+)/) {
73 18         24 shift @$desc;
74 18 50       47 my $value = $flag eq ':' ? 1 : shift @$desc;
75 18 100       48 if ($fields->{"cf_$key"}) {
76 3         16 $config{"cf_$key"} = $value;
77             } else {
78 15 50       103 my $sub = $self->can("option_$key")
79             or die "Unknown ArgType option $key";
80 15         66 push @tasks, [$sub, $value];
81             }
82             # $sub->($self, $fullclass, $value);
83             } else {
84 0         0 die "Unknown desc type $desc"
85             }
86             }
87              
88             # base だけは eval を使う。 さもないと %FIELDS が作られない。
89             # *{globref($fullclass, 'ISA')} = [$self->{cf_base}];
90             $self->checked_eval
91             (sprintf qq{package %s; use base qw(%s)}
92             , $fullclass
93             , $self->lookup_in($self->{cf_type_map}, $config{cf_base})
94 21   66     82 || $$self{cf_base});
95              
96 21         55 foreach my $rec (@symbols) {
97 9         23 my ($sym, $code) = @$rec;
98 9         15 *{globref($fullclass, $sym)} = $code;
  9         26  
99             }
100              
101 21         64 foreach my $rec (@tasks) {
102 15         33 my ($sub, $value) = @$rec;
103 15         39 $sub->($self, $fullclass, $value, \%config);
104             }
105             }
106              
107             sub lookup_in {
108 21     21 0 51 my ($self, $hash, $key) = @_;
109 21 100       156 return unless defined $key;
110 3         21 $hash->{$key};
111             }
112              
113             sub option_alias {
114 9     9 0 18 (my MY $self, my ($class, $value)) = @_;
115 9 100       30 foreach my $alias (ref $value ? @$value : $value) {
116 12         92 $self->{cf_type_map}{$alias} = $class;
117             }
118             }
119              
120             sub option_fields {
121 6     6 0 14 (my MY $self, my ($class, $value)) = @_;
122 6         24 my $fields = terse_dump(@$value);
123 6         326 $self->checked_eval(<
124             package $class; use YATT::Fields $fields;
125             END
126             }
127              
128             1;