/[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.21 - (hide annotations) (download)
Wed Nov 13 08:08:52 2002 UTC (22 years ago) by wakaba
Branch: MAIN
CVS Tags: before-dis2-200411, manakai-release-0-3-2, manakai-release-0-3-1, manakai-release-0-4-0, manakai-200612, msg-0-1, HEAD
Branch point for: branch-suikawiki-1, experimental-xml-parser-200401, stable
Changes since 1.20: +10 -10 lines
2002-08-05  Wakaba <w@suika.fam.cx>

	* Util.pm:
	- (sprintxf): Use Message::Util::Wide::unquote_if_quoted_string
	instead of Message::Util::unquote_if_quoted_string.
	- (Message::Util::Wide): New package.
	- (%Message::Util::Wide::REG): New hash.
	- (Message::Util::unquote_if_quoted_string): New function.
	- NOTE: "Wide" package is created to support utf8 string
	of perl 5.7.3 or later.  Utf8 string does not work
	only for [\x00-\xFF] regex of current functions,
	and this regex is used as (?:.|\x0D|\x0A).  (Without
	's' option, "." does not match with newline character.)
	When we can do away problematic code from all
	Message::* modules, we can also do away "Wide" package.

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

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24