/[suikacvs]/messaging/manakai/lib/Message/Field/Structured.pm
Suika

Contents of /messaging/manakai/lib/Message/Field/Structured.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.19 - (hide annotations) (download)
Sun Jul 21 03:25:00 2002 UTC (22 years, 4 months ago) by wakaba
Branch: MAIN
Changes since 1.18: +8 -2 lines
2002-07-21  Wakaba <w@suika.fam.cx>

	* Structured.pm (_parse_value): Inherit header_default_charset,
	header_default_charset_input, body_default_charset,
	body_default_charset_input.

1 wakaba 1.1
2     =head1 NAME
3    
4 wakaba 1.14 Message::Field::Structured --- A Perl Module for Internet
5     Message Structured Header Field Bodies
6 wakaba 1.1
7     =cut
8    
9     package Message::Field::Structured;
10     use strict;
11 wakaba 1.11 use vars qw(%DEFAULT $VERSION);
12 wakaba 1.19 $VERSION=do{my @r=(q$Revision: 1.18 $=~/\d+/g);sprintf "%d."."%02d" x $#r,@r};
13 wakaba 1.3 require Message::Util;
14 wakaba 1.5 use overload '""' => sub { $_[0]->stringify },
15     '.=' => sub { $_[0]->value_append ($_[1]) },
16 wakaba 1.14 #'eq' => sub { $_[0]->{field_body} eq $_[1] },
17     #'ne' => sub { $_[0]->{field_body} ne $_[1] },
18 wakaba 1.5 fallback => 1;
19 wakaba 1.1
20 wakaba 1.5 =head1 CONSTRUCTORS
21 wakaba 1.1
22 wakaba 1.5 The following methods construct new C<Message::Field::Structured> objects:
23 wakaba 1.1
24 wakaba 1.5 =over 4
25 wakaba 1.1
26 wakaba 1.5 =cut
27 wakaba 1.1
28 wakaba 1.5 ## Initialize of this class -- called by constructors
29 wakaba 1.11 %DEFAULT = (
30 wakaba 1.9 _ARRAY_NAME => '',
31 wakaba 1.11 _ARRAY_VALTYPE => '*default',
32 wakaba 1.9 _HASH_NAME => '',
33 wakaba 1.14 _METHODS => [qw|as_plain_string value_append|],
34 wakaba 1.11 _MEMBERS => [qw|field_body|],
35 wakaba 1.14 _VALTYPE_DEFAULT => '*default',
36 wakaba 1.10 by => 'index', ## (Reserved for method level option)
37 wakaba 1.9 dont_croak => 0, ## Don't die unless very very fatal error
38     encoding_after_encode => '*default',
39     encoding_before_decode => '*default',
40     field_param_name => '',
41     field_name => 'x-structured',
42 wakaba 1.14 #field_ns => '',
43 wakaba 1.9 format => 'mail-rfc2822',
44 wakaba 1.16 ## MIME charset name of '*default' charset
45     header_default_charset => 'iso-2022-int-1',
46     header_default_charset_input => 'iso-2022-int-1',
47 wakaba 1.9 hook_encode_string => #sub {shift; (value => shift, @_)},
48     \&Message::Util::encode_header_string,
49     hook_decode_string => #sub {shift; (value => shift, @_)},
50     \&Message::Util::decode_header_string,
51 wakaba 1.19 internal_charset_name => 'utf-8',
52 wakaba 1.9 #name ## Reserved for method level option
53     #parse ## Reserved for method level option
54     parse_all => 0,
55     prepend => 0, ## (Reserved for method level option)
56     value_type => {'*default' => [':none:']},
57 wakaba 1.11 );
58     sub _init ($;%) {
59     my $self = shift;
60     my %options = @_;
61     $self->{option} = Message::Util::make_clone (\%DEFAULT);
62 wakaba 1.5 $self->{field_body} = '';
63    
64     for my $name (keys %options) {
65     if (substr ($name, 0, 1) eq '-') {
66     $self->{option}->{substr ($name, 1)} = $options{$name};
67     } elsif (lc $name eq 'body') {
68     $self->{field_body} = $options{$name};
69     }
70     }
71 wakaba 1.13 $self->{comment} = [];
72 wakaba 1.5 }
73 wakaba 1.3
74 wakaba 1.5 =item Message::Field::Structured->new ([%options])
75 wakaba 1.1
76 wakaba 1.5 Constructs a new C<Message::Field::Structured> object. You might pass some
77     options as parameters to the constructor.
78 wakaba 1.1
79     =cut
80    
81 wakaba 1.2 sub new ($;%) {
82 wakaba 1.3 my $class = shift;
83 wakaba 1.5 my $self = bless {}, $class;
84     $self->_init (@_);
85 wakaba 1.3 $self;
86 wakaba 1.1 }
87    
88 wakaba 1.5 =item Message::Field::Structured->parse ($field-body, [%options])
89 wakaba 1.1
90 wakaba 1.5 Constructs a new C<Message::Field::Structured> object with
91     given field body. You might pass some options as parameters to the constructor.
92 wakaba 1.1
93     =cut
94    
95 wakaba 1.2 sub parse ($$;%) {
96 wakaba 1.3 my $class = shift;
97 wakaba 1.5 my $self = bless {}, $class;
98     $self->_init (@_);
99     #my $field_body = $self->Message::Util::decode_qcontent (shift);
100     $self->{field_body} = shift; #$field_body;
101 wakaba 1.1 $self;
102     }
103    
104 wakaba 1.5 =back
105    
106 wakaba 1.9 =cut
107    
108     ## Template procedures for array/hash fields
109     ## (As bare Message::Field::Structured module,
110     ## these shall not be used.)
111    
112     sub add ($$$%) {
113     my $self = shift;
114    
115     my $array = $self->{option}->{_ARRAY_NAME};
116     if ($array) {
117    
118     ## --- field is non-named value list (i.e. not hash)
119    
120     ## Options
121     my %option = %{$self->{option}};
122     if (ref $_[0] eq 'HASH') {
123     my $option = shift (@_);
124     for (keys %$option) {my $n = $_; $n =~ s/^-//; $option{$n} = $$option{$_}}
125     }
126 wakaba 1.11 $option{parse} = 1 if defined wantarray && !defined $option{parse};
127     $option{parse} = 1 if $option{parse_all} && !defined $option{parse};
128 wakaba 1.9
129     ## Additional items
130     my $avalue;
131     for (@_) {
132 wakaba 1.11 local $option{parse} = $option{parse};
133 wakaba 1.14 my $ok;
134     ($ok, undef, $avalue) = $self->_add_array_check ($_, \%option);
135 wakaba 1.9 if ($ok) {
136 wakaba 1.11 $avalue = $self->_parse_value
137     ($option{_ARRAY_VALTYPE} => $avalue) if $option{parse};
138 wakaba 1.9 if ($option{prepend}) {
139     unshift @{$self->{$array}}, $avalue;
140     } else {
141     push @{$self->{$array}}, $avalue;
142     }
143     }
144     }
145 wakaba 1.14 $self->_add_return_value (\$avalue, \%option);
146     ## Return last added value if necessary.
147 wakaba 1.9
148     } else {
149     $array = $self->{option}->{_HASH_NAME};
150    
151     ## --- field is not list
152    
153     unless ($array) {
154     my %option = @_;
155     return if $option{-dont_croak};
156     Carp::croak q{add: Method not available for this module};
157     }
158    
159     ## --- field is named value list (i.e. hash)
160    
161     ## Options
162     my %p = @_; my %option = %{$self->{option}};
163     for (grep {/^-/} keys %p) {$option{substr ($_, 1)} = $p{$_}}
164     $option{parse} = 1 if defined wantarray && !defined $option{parse};
165 wakaba 1.11 $option{parse} = 1 if $option{parse_all} && !defined $option{parse};
166 wakaba 1.9
167     ## Additional items
168     my $avalue;
169     while (my ($name => $value) = splice (@_, 0, 2)) {
170     next if $name =~ /^-/; $name =~ s/^\\//;
171 wakaba 1.14 $name =~ tr/_/-/ if $option{translate_underscore};
172 wakaba 1.9
173     my $ok;
174 wakaba 1.11 local $option{parse} = $option{parse};
175 wakaba 1.10 ($ok, $name, $avalue) = $self->_add_hash_check ($name => $value, \%option);
176 wakaba 1.9 if ($ok) {
177 wakaba 1.10 $avalue = $self->_parse_value ($name => $avalue) if $option{parse};
178 wakaba 1.9 if ($option{prepend}) {
179     unshift @{$self->{$array}}, $avalue;
180     } else {
181     push @{$self->{$array}}, $avalue;
182     }
183     }
184     }
185 wakaba 1.14 $self->_add_return_value (\$avalue, \%option);
186     ## Return last added value if necessary.
187 wakaba 1.9 }
188     }
189    
190     sub _add_array_check ($$\%) {
191     shift; 1, $_[0] => $_[0];
192     }
193     sub _add_hash_check ($$$\%) {
194     shift; 1, $_[0] => [@_[0,1]];
195     }
196 wakaba 1.14 ## Returns returned item value \$item-value, \%option
197     sub _add_return_value ($\$\%) {
198     $_[1];
199     }
200 wakaba 1.9
201     sub replace ($$$%) {
202     my $self = shift;
203    
204     $self->_replace_cleaning;
205     my $array = $self->{option}->{_ARRAY_NAME};
206     if ($array) {
207    
208     ## --- field is non-named value list (i.e. not hash)
209    
210     ## Options
211     my %option = %{$self->{option}};
212     if (ref $_[0] eq 'HASH') {
213     my $option = shift (@_);
214     for (keys %$option) {my $n = $_; $n =~ s/^-//; $option{$n} = $$option{$_}}
215     }
216 wakaba 1.11 $option{parse} = 1 if defined wantarray && !defined $option{parse};
217     $option{parse} = 1 if $option{parse_all} && !defined $option{parse};
218 wakaba 1.9
219     ## Additional items
220     my ($avalue, %replace);
221     for (@_) {
222 wakaba 1.11 local $option{parse} = $option{parse};
223 wakaba 1.9 my ($ok, $aname);
224     ($ok, $aname => $avalue)
225     = $self->_replace_array_check ($_, \%option);
226     if ($ok) {
227 wakaba 1.11 $avalue = $self->_parse_value
228     ($option{_ARRAY_VALTYPE} => $avalue) if $option{parse};
229 wakaba 1.9 $replace{$aname} = $avalue;
230     }
231     }
232     for (@{$self->{$array}}) {
233     my ($v) = $self->_replace_array_shift (\%replace => $_, \%option);
234     if (defined $v) {
235     $_ = $v;
236     }
237     }
238     for (keys %replace) {
239     if ($option{prepend}) {
240     unshift @{$self->{$array}}, $replace{$_};
241     } else {
242     push @{$self->{$array}}, $replace{$_};
243     }
244     }
245 wakaba 1.14 $self->_replace_return_value (\$avalue, \%option);
246     ## Return last added value if necessary.
247 wakaba 1.9
248     } else {
249     $array = $self->{option}->{_HASH_NAME};
250    
251     ## --- field is not list
252    
253     unless ($array) {
254     my %option = @_;
255     return if $option{-dont_croak};
256     Carp::croak q{replace: Method not available for this module};
257     }
258    
259     ## --- field is named value list (i.e. hash)
260    
261     ## Options
262     my %p = @_; my %option = %{$self->{option}};
263     for (grep {/^-/} keys %p) {$option{substr ($_, 1)} = $p{$_}}
264     $option{parse} = 1 if defined wantarray && !defined $option{parse};
265 wakaba 1.11 $option{parse} = 1 if $option{parse_all} && !defined $option{parse};
266 wakaba 1.9
267     ## Additional items
268     my ($avalue, %replace);
269     while (my ($name => $value) = splice (@_, 0, 2)) {
270     next if $name =~ /^-/; $name =~ s/^\\//;
271 wakaba 1.14 $name =~ tr/_/-/ if $option{translate_underscore};
272 wakaba 1.9
273     my ($ok, $aname);
274 wakaba 1.11 local $option{parse} = $option{parse};
275 wakaba 1.9 ($ok, $aname => $avalue)
276     = $self->_replace_hash_check ($name => $value, \%option);
277     if ($ok) {
278 wakaba 1.11 $avalue = $self->_parse_value ($name => $avalue) if $option{parse};
279 wakaba 1.9 $replace{$aname} = $avalue;
280     }
281     }
282     for (@{$self->{$array}}) {
283 wakaba 1.14 last unless keys %replace;
284 wakaba 1.9 my ($v) = $self->_replace_hash_shift (\%replace => $_, \%option);
285     if (defined $v) {
286     $_ = $v;
287     }
288     }
289     for (keys %replace) {
290     if ($option{prepend}) {
291     unshift @{$self->{$array}}, $replace{$_};
292     } else {
293     push @{$self->{$array}}, $replace{$_};
294     }
295     }
296 wakaba 1.14 $self->_replace_return_value (\$avalue, \%option);
297     ## Return last added value if necessary.
298 wakaba 1.9 }
299     }
300    
301 wakaba 1.17 ## $self->_replace_cleaning
302     ## -- Cleans the array/hash before replacing
303 wakaba 1.9 sub _replace_cleaning ($) {
304 wakaba 1.10 $_[0]->_delete_empty;
305 wakaba 1.9 }
306 wakaba 1.17 #*_replace_cleaning = \&_delete_empty;
307     ## Be not aliasing for inheriting class
308    
309     ## (1/0, $name => $value) = $self->_replace_array_check ($value, \%option)
310     ## -- Checks given value and prepares saving value (array version)
311     ## Note that $name of return value is used as key for _replace_array_shift.
312     ## Usually, it is same as $value.
313     ## Note: In many case, same code as _add_array_check can be used.
314 wakaba 1.9 sub _replace_array_check ($$\%) {
315     shift; 1, $_[0] => $_[0];
316     }
317 wakaba 1.17
318     ## $value = $self->_replace_array_shift (\%values, $name, $option)
319     ## -- Returns a value (from %values, with key of $name) and deletes
320     ## it from %values (like CORE::shift for array) (array version)
321 wakaba 1.9 sub _replace_array_shift ($\%$\%) {
322     shift; my $r = shift; my $n = $_[0]->[0];
323     if ($$r{$n}) {
324     my $d = $$r{$n};
325     $$r{$n} = undef;
326     return $d;
327     }
328     undef;
329     }
330 wakaba 1.17
331     ## (1/0, $name => $value) = $self->_replace_hash_check ($name => $value, \%option)
332     ## -- Checks given value and prepares saving value (hash version)
333     ## Note: In many case, same code as _add_hash_check can be used.
334 wakaba 1.9 sub _replace_hash_check ($$$\%) {
335     shift; 1, $_[0] => [@_[0,1]];
336     }
337 wakaba 1.17
338     ## $value = $self->_replace_hash_shift (\%values, $name, $option)
339     ## -- Returns a value (from %values, with key of $name) and
340     ## deletes it from %values (like CORE::shift for array) (hash version)
341 wakaba 1.9 sub _replace_hash_shift ($\%$\%) {
342     shift; my $r = shift; my $n = $_[0]->[0];
343     if ($$r{$n}) {
344     my $d = $$r{$n};
345     $$r{$n} = undef;
346     return $d;
347     }
348     undef;
349     }
350 wakaba 1.17
351     ## $value = $self->_replace_return_value (\$item, \%option)
352     ## -- Returns returning value of replace method
353     ## Note: Usually this can share code with _item_return_value.
354 wakaba 1.14 sub _replace_return_value ($\$\%) {
355     $_[1];
356     }
357 wakaba 1.9
358 wakaba 1.17 ## TODO: Implement count by any and merge with item_exist
359 wakaba 1.9 sub count ($;%) {
360     my $self = shift; my %option = @_;
361     my $array = $self->{option}->{_ARRAY_NAME}
362     || $self->{option}->{_HASH_NAME};
363     unless ($array) {
364     return if $option{-dont_croak};
365     Carp::croak q{count: Method not available for this module};
366     }
367     $self->_count_cleaning;
368     return $self->_count_by_name ($array => \%option) if defined $option{-name};
369     $#{$self->{$array}} + 1;
370     }
371 wakaba 1.17
372     ## $self->_count_cleaning
373     ## -- Cleans the array/hash before counting
374 wakaba 1.9 sub _count_cleaning ($) {
375 wakaba 1.10 $_[0]->_delete_empty;
376 wakaba 1.9 }
377 wakaba 1.17
378 wakaba 1.9 sub _count_by_name ($$\%) {
379     # my $self = shift;
380     # my ($array, $option) = @_;
381     # my $name = $self->_n11n_*name* ($$option{-name});
382     # my @a = grep {$_->[0] eq $name} @{$self->{$array}};
383     # $#a + 1;
384     }
385    
386 wakaba 1.10 sub delete ($@) {
387     my $self = shift;
388     my %p; %p = %{shift (@_)} if ref $_[0] eq 'HASH';
389     my %option = %{$self->{option}};
390     for (grep {/^-/} keys %p) {$option{substr ($_, 1)} = $p{$_}}
391     my $array = $option{_ARRAY_NAME} || $option{_HASH_NAME};
392     unless ($array) {
393     return if $option{dont_croak};
394     Carp::croak q{delete: Method not available for this module};
395     }
396     if ($option{by} && $option{by} ne 'index') {
397     my %name; for (@_) {$name{$_} = 1}
398     for (@{$self->{$array}}) {
399     if ($self->_delete_match ($option{by}, \$_, \%name, \%option)) {
400     $_ = undef;
401     }
402     }
403     } else { ## by index
404     for (@_) {
405     $self->{$array}->[$_] = undef;
406     }
407     }
408     $self->_delete_cleaning;
409     }
410    
411 wakaba 1.17 ## 1/0 = $self->_delete_match ($by, \$item, \%delete_list, \%option)
412     ## -- Checks and returns whether given item is matched with
413     ## deleting item list
414     ## Note: Usually this code can be shared with _item_match.
415     ## Note: $by eq 'index' is already defined in delete method
416     ## itself, so in this function it need not be checked.
417 wakaba 1.10 sub _delete_match ($$\$\%\%) {
418 wakaba 1.17 my $self = shift;
419     my ($by, $item, $list, $option) = @_;
420     return 0 unless ref $$item; ## Already removed
421     ## An example definition
422     if ($by eq 'name') {
423     $$item->{value} = $self->_parse_value ($$item->{type}, $$item->{value});
424     return 1 if ref $$item->{value} && $$list{ $$item->{value}->{name} };
425     }
426     0;
427 wakaba 1.10 }
428    
429     sub _delete_cleaning ($) {
430     $_[0]->_delete_empty;
431     }
432    
433 wakaba 1.9 ## Delete empty items
434     sub _delete_empty ($) {
435 wakaba 1.11 my $self = shift;
436     my $array = $self->{option}->{_ARRAY_NAME} || $self->{option}->{_HASH_NAME};
437     $self->{$array} = [grep {length $_} @{$self->{$array}}] if $array;
438 wakaba 1.9 }
439    
440 wakaba 1.10 sub item ($$;%) {
441     my $self = shift;
442 wakaba 1.17 my ($name, %p) = (shift, @_);
443     ## BUG: don't support -by
444 wakaba 1.10 return $self->replace ($name => $p{-value}, @_) if defined $p{-value};
445     my %option = %{$self->{option}};
446 wakaba 1.11 $option{new_item_unless_exist} = 1;
447 wakaba 1.10 for (grep {/^-/} keys %p) {$option{substr ($_, 1)} = $p{$_}}
448     my $array = $option{_ARRAY_NAME} || $option{_HASH_NAME};
449     unless ($array) {
450     return if $option{dont_croak};
451     Carp::croak q{item: Method not available for this module};
452     }
453 wakaba 1.18 $option{parse} = 1 unless defined $option{parse};
454     $option{parse} = 1 if $option{parse_all} && !defined $option{parse};
455 wakaba 1.11 my @r;
456 wakaba 1.10 if ($option{by} eq 'index') {
457     for ($self->{$array}->[$name]) {
458     return $self->_item_return_value (\$_, \%option);
459     }
460     } else {
461     for (@{$self->{$array}}) {
462     if ($self->_item_match ($option{by}, \$_, {$name => 1}, \%option)) {
463     if (wantarray) {
464     push @r, $self->_item_return_value (\$_, \%option);
465     } else {
466     return $self->_item_return_value (\$_, \%option);
467     }
468     }
469     }
470     }
471 wakaba 1.11 if (@r == 0 && $option{new_item_unless_exist}) {
472     my $v = $self->_item_new_value ($name, \%option);
473     if (defined $v) {
474     if ($option{prepend}) {
475     unshift @{$self->{$array}}, $v;
476     } else {
477     push @{$self->{$array}}, $v;
478     }
479     return $self->_item_return_value (\$v, \%option);
480     }
481     }
482     return undef unless wantarray;
483     @r;
484 wakaba 1.10 }
485    
486 wakaba 1.14 sub item_exist ($$;%) {
487     my $self = shift;
488     my ($name, %p) = (shift, @_);
489     my %option = %{$self->{option}};
490     for (grep {/^-/} keys %p) {$option{substr ($_, 1)} = $p{$_}}
491     my $array = $option{_ARRAY_NAME} || $option{_HASH_NAME};
492     unless ($array) {
493     return if $option{dont_croak};
494     Carp::croak q{item-exist: Method not available for this module};
495     }
496     my @r;
497     if ($option{by} eq 'index') {
498     return 1 if ref $self->{$array}->[$name];
499     } else {
500     for (@{$self->{$array}}) {
501     if ($self->_item_match ($option{by}, \$_, {$name => 1}, \%option)) {
502     return 1;
503     }
504     }
505     }
506     0;
507     }
508    
509 wakaba 1.17 ## 1/0 = $self->_item_match ($by, \$item, \%delete_list, \%option)
510     ## -- Checks and returns whether given item is matched with
511     ## returning item list
512     ## Note: $by eq 'index' is already defined in delete method
513     ## itself, so in this function it need not be checked.
514 wakaba 1.10 sub _item_match ($$\$\%\%) {
515 wakaba 1.17 my $self = shift;
516     my ($by, $item, $list, $option) = @_;
517     return 0 unless ref $$item; ## Removed
518     ## An example definition
519     if ($by eq 'name') {
520     $$item->{value} = $self->_parse_value ($$item->{type}, $$item->{value});
521     return 1 if ref $$item->{value} && $$list{ $$item->{value}->{name} };
522     }
523     0;
524 wakaba 1.10 }
525    
526 wakaba 1.17 ## $value = $self->_item_return_value (\$item, \%option)
527     ## -- Returns returning value of item method
528 wakaba 1.10 sub _item_return_value ($\$\%) {
529 wakaba 1.11 $_[1];
530     }
531    
532 wakaba 1.17 ## $item = $self->_item_new_value ($name, \%option)
533     ## -- Returns new item with key of $name (called when
534     ## no returned value is found and -new_value_unless_exist
535     ## option is true)
536     ## (Note that the kind of key ('by' option) can be getten
537     ## from $option->{by})
538     ## Return undef when new value can't be generated.
539 wakaba 1.11 sub _item_new_value ($$\%) {
540     $_[1];
541 wakaba 1.10 }
542    
543 wakaba 1.9 ## $self->_parse_value ($type, $value);
544     sub _parse_value ($$$) {
545     my $self = shift;
546 wakaba 1.14 my $name = shift;
547 wakaba 1.9 my $value = shift;
548     return $value if ref $value;
549 wakaba 1.14 my $handler = $self->{option}->{value_type}->{$name}
550     || $self->{option}->{value_type}->{$self->{option}->{_VALTYPE_DEFAULT}};
551     if (ref $handler eq 'CODE') {
552     $handler = &$handler ($self);
553     }
554     my $vtype = $handler->[0];
555     my %vopt = (
556 wakaba 1.19 -body_default_charset => $self->{option}->{body_default_charset},
557     -body_default_charset_input => $self->{option}->{body_default_charset_input},
558 wakaba 1.14 -format => $self->{option}->{format},
559     -field_ns => $self->{option}->{field_ns},
560     -field_name => $self->{option}->{field_name},
561     -field_param_name => $name,
562 wakaba 1.19 -header_default_charset => $self->{option}->{header_default_charset},
563     -header_default_charset_input => $self->{option}->{header_default_charset_input},
564     -internal_charset_name => $self->{option}->{internal_charset_name},
565 wakaba 1.14 -parse_all => $self->{option}->{parse_all},
566     );
567     ## Media type specified option/parameters
568     if (ref $handler->[1] eq 'HASH') {
569     for (keys %{$handler->[1]}) {
570     $vopt{$_} = ${$handler->[1]}{$_};
571     }
572     }
573     ## Inherited options
574     if (ref $handler->[2] eq 'ARRAY') {
575     for (@{$handler->[2]}) {
576     $vopt{'-'.$_} = $self->{option}->{$_};
577     }
578     }
579    
580 wakaba 1.9 if ($vtype eq ':none:') {
581     return $value;
582     } elsif (defined $value) {
583     eval "require $vtype" or Carp::croak qq{<parse>: $vtype: Can't load package: $@};
584 wakaba 1.14 return $vtype->parse ($value, %vopt);
585 wakaba 1.9 } else {
586     eval "require $vtype" or Carp::croak qq{<parse>: $vtype: Can't load package: $@};
587 wakaba 1.14 return $vtype->new (%vopt);
588 wakaba 1.9 }
589     }
590    
591 wakaba 1.11 ## comments
592    
593    
594     sub comment_add ($@) {
595     my $self = shift;
596     my $array = 'comment';
597     ## Options
598     my %option = %{$self->{option}};
599     if (ref $_[0] eq 'HASH') {
600     my $option = shift (@_);
601     for (keys %$option) {my $n = $_; $n =~ s/^-//; $option{$n} = $$option{$_}}
602     }
603    
604     ## Additional items
605     if ($option{prepend}) {
606     unshift @{$self->{$array}}, reverse @_;
607     } else {
608     push @{$self->{$array}}, @_;
609     }
610     }
611    
612     sub comment_count ($) {
613     my $self = shift;
614     $self->_comment_cleaning;
615     $#{$self->{comment}} + 1;
616     }
617    
618     sub comment_delete ($@) {
619     my $self = shift;
620     #my %p; %p = %{shift (@_)} if ref $_[0] eq 'HASH';
621     #my %option = %{$self->{option}};
622     #for (grep {/^-/} keys %p) {$option{substr ($_, 1)} = $p{$_}}
623     for (@_) {
624     $self->{comment}->[$_] = undef;
625     }
626     $self->_comment_cleaning;
627     }
628    
629     sub comment_item ($$) {
630     $_[0]->{comment}->[$_[1]];
631     }
632    
633     sub _comment_cleaning ($) {
634     my $self = shift;
635     $self->{comment} = [grep {length $_} @{$self->{comment}}];
636     }
637    
638     sub _comment_stringify ($\%) {
639     my $self = shift;
640 wakaba 1.15 my $option = shift;
641     $option->{_comment_min} ||= 0;
642     $option->{_comment_max} = $#{$self->{comment}} unless defined $option->{_comment_max};
643 wakaba 1.11 my @v;
644 wakaba 1.15 for (@{$self->{comment}}[$option->{_comment_min}..$option->{_comment_max}]) {
645 wakaba 1.11 push @v, '('. $self->Message::Util::encode_ccontent ($_) .')';
646     }
647     join ' ', @v;
648     }
649    
650 wakaba 1.14 sub scan ($&;%) {
651     my $self = shift;
652     my $sub = shift;
653 wakaba 1.16 my %p = @_; my %option;
654     if (ref $p{options} eq 'HASH') {
655     %option = %{$p{options}};
656     } else {
657     %option = %{$self->{option}};
658     for (grep {/^-/} keys %p) {$option{substr ($_, 1)} = $p{$_}}
659     }
660     my $array = $option{_ARRAY_NAME} || $option{_HASH_NAME};
661     my @param = $self->_scan_sort (\@{$self->{$array}}, \%option);
662 wakaba 1.14 #my $sort = $option{sort};
663     #@param = sort $sort @param if ref $sort;
664 wakaba 1.10 for my $param (@param) {
665 wakaba 1.16 &$sub($self, $param, \%option);
666 wakaba 1.10 }
667     }
668    
669 wakaba 1.14 sub _scan_sort ($\@) {
670     #my $self = shift;
671     @{$_[1]};
672     }
673    
674 wakaba 1.5 =head1 METHODS
675    
676     =over 4
677    
678     =item $self->stringify ([%options])
679 wakaba 1.1
680 wakaba 1.5 Returns field body as a string. Returned string is encoded,
681     quoted if necessary (by C<hook_encode_string>).
682 wakaba 1.1
683     =cut
684    
685 wakaba 1.7 sub stringify ($;%) {
686 wakaba 1.1 my $self = shift;
687 wakaba 1.5 #$self->Message::Util::encode_qcontent ($self->{field_body});
688     $self->{field_body};
689 wakaba 1.1 }
690 wakaba 1.5 *as_string = \&stringify;
691 wakaba 1.1
692 wakaba 1.5 =item $self->as_plain_string
693 wakaba 1.1
694 wakaba 1.5 Returns field body as a string. Returned string is not encoded
695     or quoted, i.e. internal/bare coded string. This string
696     may be unable to use as field body content. (Its I<structures>
697     such as C<comment> and C<quoted-string> are lost.)
698 wakaba 1.1
699     =cut
700    
701     sub as_plain_string ($) {
702     my $self = shift;
703 wakaba 1.5 my $s = $self->Message::Util::decode_qcontent ($self->{field_body});
704     Message::Util::unquote_quoted_string (Message::Util::unquote_ccontent ($s));
705 wakaba 1.1 }
706 wakaba 1.4
707 wakaba 1.5 =item $self->option ( $option-name / $option-name, $option-value, ...)
708 wakaba 1.4
709 wakaba 1.5 If @_ == 1, returns option value. Else...
710 wakaba 1.4
711 wakaba 1.5 Set option value. You can pass multiple option name-value pair
712     as parameter. Example:
713 wakaba 1.1
714 wakaba 1.5 $msg->option (format => 'mail-rfc822',
715     capitalize => 0);
716     print $msg->option ('format'); ## mail-rfc822
717 wakaba 1.1
718     =cut
719    
720 wakaba 1.5 sub option ($@) {
721 wakaba 1.1 my $self = shift;
722 wakaba 1.5 if (@_ == 1) {
723     return $self->{option}->{ $_[0] };
724     }
725 wakaba 1.14 my %option = @_;
726 wakaba 1.5 while (my ($name, $value) = splice (@_, 0, 2)) {
727 wakaba 1.14 $self->{option}->{$name} = $value;
728     }
729     if ($option{-recursive}) {
730     $self->_option_recursive (\%option);
731 wakaba 1.5 }
732 wakaba 1.12 $self;
733 wakaba 1.1 }
734    
735 wakaba 1.14 ## $self->_option_recursive (\%argv)
736     sub _option_recursive ($\%) {}
737    
738 wakaba 1.9 ## TODO: multiple value-type support
739     sub value_type ($;$$%) {
740     my $self = shift;
741 wakaba 1.14 my $name = shift || $self->{option}->{_VALTYPE_DEFAULT};
742 wakaba 1.9 my $new_value_type = shift;
743     if ($new_value_type) {
744     $self->{option}->{value_type}->{$name} = []
745     unless ref $self->{option}->{value_type}->{$name};
746     $self->{option}->{value_type}->{$name}->[0] = $new_value_type;
747     }
748     if (ref $self->{option}->{value_type}->{$name}) {
749     $self->{option}->{value_type}->{$name}->[0]
750 wakaba 1.14 || $self->{option}->{value_type}->{$self->{option}->{_VALTYPE_DEFAULT}}->[0];
751 wakaba 1.9 } else {
752 wakaba 1.14 $self->{option}->{value_type}->{$self->{option}->{_VALTYPE_DEFAULT}}->[0];
753 wakaba 1.9 }
754     }
755    
756 wakaba 1.5 =item $self->clone ()
757 wakaba 1.1
758 wakaba 1.5 Returns a copy of Message::Field::Structured object.
759 wakaba 1.1
760     =cut
761    
762 wakaba 1.5 sub clone ($) {
763 wakaba 1.1 my $self = shift;
764 wakaba 1.5 my $clone = ref($self)->new;
765 wakaba 1.9 $clone->{option} = Message::Util::make_clone ($self->{option});
766 wakaba 1.5 ## Common hash value (not used in this module)
767 wakaba 1.11 $self->_delete_empty;
768     $self->_comment_cleaning;
769     $clone->{value} = Message::Util::make_clone ($self->{value});
770     $clone->{comment} = Message::Util::make_clone ($self->{comment});
771     for (@{$self->{option}->{_MEMBERS}}) {
772     $clone->{$_} = Message::Util::make_clone ($self->{$_});
773     }
774 wakaba 1.5 $clone;
775 wakaba 1.1 }
776    
777 wakaba 1.8
778 wakaba 1.10 my %_method_default_list = qw(new 1 parse 1 stringify 1 option 1 clone 1 method_available 1);
779     sub method_available ($$) {
780     my $self = shift;
781     my $name = shift;
782     return 1 if $_method_default_list{$name};
783     for (@{$self->{option}->{_METHODS}}) {
784     return 1 if $_ eq $name;
785     }
786     0;
787     }
788 wakaba 1.5
789 wakaba 1.1 =head1 EXAMPLE
790    
791     use Message::Field::Structured;
792    
793     my $field_body = '"This is an example of <\"> (quotation mark)."
794     (Comment within \q\u\o\t\e\d\-\p\a\i\r\(\s\))';
795     my $field = Message::Field::Structured->parse ($field_body);
796    
797     print $field->as_plain_string;
798    
799 wakaba 1.5 =head1 SEE ALSO
800    
801     =over 4
802    
803     =item L<Message::Entity>, L<Message::Header>
804    
805     =item L<Message::Field::Unstructured>
806    
807     =item RFC 2822 E<lt>urn:ietf:rfc:2822E<gt>, usefor-article, HTTP/1.0, HTTP/1.1
808    
809     =back
810    
811 wakaba 1.1 =head1 LICENSE
812    
813     Copyright 2002 wakaba E<lt>w@suika.fam.cxE<gt>.
814    
815     This program is free software; you can redistribute it and/or modify
816     it under the terms of the GNU General Public License as published by
817     the Free Software Foundation; either version 2 of the License, or
818     (at your option) any later version.
819    
820     This program is distributed in the hope that it will be useful,
821     but WITHOUT ANY WARRANTY; without even the implied warranty of
822     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
823     GNU General Public License for more details.
824    
825     You should have received a copy of the GNU General Public License
826     along with this program; see the file COPYING. If not, write to
827     the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
828     Boston, MA 02111-1307, USA.
829    
830     =head1 CHANGE
831    
832     See F<ChangeLog>.
833 wakaba 1.19 $Date: 2002/07/06 10:30:43 $
834 wakaba 1.1
835     =cut
836    
837     1;

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24