File Coverage

blib/lib/Unicode/Emoji/Base.pm
Criterion Covered Total %
statement 89 91 97.8
branch 11 20 55.0
condition 2 2 100.0
subroutine 21 22 95.4
pod 0 1 0.0
total 123 136 90.4


line stmt bran cond sub pod time code
1             =head1 NAME
2              
3             Unicode::Emoji::Base - Base class for Unicode::Emoji::* classes
4              
5             =head1 DESCRIPTION
6              
7             This is a base class for Unicode::Emoji::* classes.
8             You B need to use this directly.
9              
10             =head1 AUTHOR
11              
12             Yusuke Kawasaki, L
13              
14             =head1 SEE ALSO
15              
16             L
17              
18             =head1 COPYRIGHT
19              
20             Copyright 2009 Yusuke Kawasaki, all rights reserved.
21              
22             =cut
23              
24             package Unicode::Emoji::Base;
25 7     7   14439 use XML::TreePP;
  7         104694  
  7         283  
26 7     7   20150 use Any::Moose;
  7         344291  
  7         56  
27             has verbose => (is => 'rw', isa => 'Bool');
28             has datadir => (is => 'rw', isa => 'Str', lazy_build => 1);
29             has treepp => (is => 'rw', isa => 'XML::TreePP', lazy_build => 1);
30              
31             our $VERSION = '0.03';
32              
33             our $DATADIR = 'http://emoji4unicode.googlecode.com/svn/trunk/data/';
34             # our $DATADIR = 'data/';
35              
36             sub _build_datadir {
37 5     5   1786 $DATADIR;
38             }
39              
40             our $TREEPP_OPT = {
41             force_array => [qw(category subcategory e ann)],
42             attr_prefix => '',
43             utf8_flag => 1,
44             };
45              
46             sub _build_treepp {
47 5     5   22 my $self = shift;
48 5         98 XML::TreePP->new(%$TREEPP_OPT);
49             }
50              
51             our $CONFIG_COLUMNS = [qw(verbose datadir treepp)];
52              
53             sub clone_config {
54 12     12 0 24 my $self = shift;
55 12         65 map { $_ => $self->{$_} } grep { exists $self->{$_} } @$CONFIG_COLUMNS;
  12         215  
  36         206  
56             }
57              
58             package Unicode::Emoji::Base::File;
59 7     7   6577 use Any::Moose;
  7         15  
  7         30  
60             extends 'Unicode::Emoji::Base';
61             has dataxml => (is => 'rw', isa => 'Str', lazy_build => 1);
62             has root => (is => 'rw', isa => 'Ref', lazy_build => 1);
63              
64             sub _build_dataxml {
65 4     4   13 my $self = shift;
66 4         77 my $datadir = $self->datadir;
67 4         31 $datadir =~ s#/?$#/#;
68 4         26 $datadir.$self->_dataxml;
69             }
70              
71             sub _build_root {
72 4     4   11 my $self = shift;
73              
74             # data/docomo/carrier_data.xml or
75             # http://emoji4unicode.googlecode.com/svn/trunk/data/docomo/carrier_data.xml
76 4         65 my $dataxml = $self->dataxml;
77              
78             # element class name
79 4         15 my $elem_class = (ref $self).'::XML';
80 4         73 my $save = $self->treepp->get('elem_class');
81 4         138 $self->treepp->set(elem_class => $elem_class);
82              
83             # verbose message
84 4 50       74 print STDERR $dataxml, "\n" if $self->verbose;
85              
86             # fetch and parse
87 4         16 my $data;
88 4 50       30 if ($dataxml =~ m#^https?://#) {
89 4         38 $data = $self->treepp->parsehttp(GET => $dataxml);
90             } else {
91 0         0 $data = $self->treepp->parsefile($dataxml);
92             }
93              
94             # restore
95 4         1774144 $self->treepp->set(elem_class => $save);
96              
97             # root element
98 4         51 my $root = (values %$data)[0];
99 4         143 $root;
100             }
101              
102 0     0   0 sub xmlfile { Carp::croak 'xmlfile not implemented: '.(ref $_[0]); }
103              
104             sub index {
105 5     5   12 my $self = shift;
106 5         12 my $key = shift;
107 5   100     111 $self->{index} ||= {};
108 5 100       50 return $self->{index}->{$key} if ref $self->{index}->{$key};
109              
110 4         31 my $list = $self->list;
111 4         25 my @notnull = grep {ref $_} @$list;
  2246         2843  
112 4 50       23 Carp::croak "Null list\n" unless scalar @notnull;
113              
114 4         18 my @translate = grep {defined $_->$key()} @notnull;
  2246         6612  
115 4 50       28 Carp::croak "Invalid index key: $key" unless scalar @translate;
116              
117             # cache
118 4         27 $self->{index}->{$key} = {map {$_->$key() => $_} @translate };
  2220         13066  
119 4         476 $self->{index}->{$key};
120             }
121              
122             sub find {
123 5     5   3834 my $self = shift;
124 5         14 my $key = shift;
125 5         12 my $val = shift;
126 5 50       43 my $index = $self->index($key) or return;
127 5 50       26 return unless exists $index->{$val};
128 5         29 $index->{$val};
129             }
130              
131             package Unicode::Emoji::Base::File::Carrier;
132 7     7   13036 use Any::Moose;
  7         27  
  7         38  
133             extends 'Unicode::Emoji::Base::File';
134             has list => (is => 'ro', isa => 'ArrayRef', lazy_build => 1);
135              
136             sub _build_list {
137 3     3   371 my $self = shift;
138 3         57 my $list = $self->root->e;
139 3         34 $list;
140             }
141              
142             package Unicode::Emoji::Base::Emoji;
143 7     7   11015 use Encode ();
  7         57950  
  7         256  
144 7     7   51 use Any::Moose;
  7         65  
  7         51  
145             has unicode_hex => (is => 'rw', isa => 'Str', required => 1);
146             has unicode_string => (is => 'ro', isa => 'Str', lazy_build => 1);
147             has unicode_octets => (is => 'ro', isa => 'Str', lazy_build => 1);
148             has is_alt => (is => 'ro', isa => 'Bool', lazy_build => 1);
149              
150             sub _build_unicode_string {
151 9     9   15295 my $self = shift;
152 9 50       79 my $hex = $self->unicode_hex or return;
153 9         31 $hex =~ s/^[\>\*\+]//;
154 9 50       39 return unless length $hex;
155 9         44 join "" => map {chr hex $_} split /\+/, $hex;
  9         125  
156             }
157              
158             sub _build_unicode_octets {
159 5     5   15 my $self = shift;
160 5         25 my $string = $self->unicode_string;
161 5         37 Encode::encode_utf8($string);
162             }
163              
164             sub _build_is_alt {
165 5     5   16560 my $self = shift;
166 5         103 $self->unicode_hex =~ /^>/;
167             }
168              
169             package Unicode::Emoji::Base::Emoji::CP932;
170 7     7   5694 use Encode ();
  7         14  
  7         119  
171 7     7   71 use Any::Moose;
  7         15  
  7         30  
172             extends 'Unicode::Emoji::Base::Emoji';
173             has cp932_string => (is => 'ro', isa => 'Str', lazy_build => 1);
174             has cp932_octets => (is => 'ro', isa => 'Str', lazy_build => 1);
175              
176             sub _build_cp932_octets {
177 4     4   10 my $self = shift;
178 4 50       37 my $hex = $self->unicode_hex or return;
179 4         20 $hex =~ s/^>//;
180 4         25 join "" => map {pack(n=>$self->_unicode_to_cp932(hex $_))} split /\+/, $hex;
  4         33  
181             }
182              
183             my $ENCODE_CP932 = Encode::find_encoding('cp932');
184             sub _build_cp932_string {
185 4     4   3720 my $self = shift;
186 4         63 my $octets = $self->cp932_octets;
187 4         5179 $ENCODE_CP932->decode($octets);
188             }
189              
190             __PACKAGE__->meta->make_immutable;