/[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 - (show 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
2 =head1 NAME
3
4 Message::Field::Structured --- A Perl Module for Internet
5 Message Structured Header Field Bodies
6
7 =cut
8
9 package Message::Field::Structured;
10 use strict;
11 use vars qw(%DEFAULT $VERSION);
12 $VERSION=do{my @r=(q$Revision: 1.20 $=~/\d+/g);sprintf "%d."."%02d" x $#r,@r};
13 require Message::Util;
14 use overload '""' => sub { $_[0]->stringify },
15 '.=' => sub { $_[0]->value_append ($_[1]) },
16 #'eq' => sub { $_[0]->{field_body} eq $_[1] },
17 #'ne' => sub { $_[0]->{field_body} ne $_[1] },
18 fallback => 1;
19
20 ## Initialize of this class -- called by constructors
21 %DEFAULT = (
22 _ARRAY_NAME => '',
23 _ARRAY_VALTYPE => '*default',
24 _HASH_NAME => '',
25 _METHODS => [qw|as_plain_string value_append|],
26 _MEMBERS => [qw|field_body|],
27 _VALTYPE_DEFAULT => '*default',
28 by => 'index', ## (Reserved for method level option)
29 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 #field_ns => '',
35 format => 'mail-rfc2822',
36 ## MIME charset name of '*default' charset
37 header_default_charset => 'iso-2022-int-1',
38 header_default_charset_input => 'iso-2022-int-1',
39 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 internal_charset_name => 'utf-8',
44 #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 );
50 sub _init ($;%) {
51 my $self = shift;
52 my %options = @_;
53 $self->{option} = Message::Util::make_clone (\%DEFAULT);
54 $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 } elsif ($name eq 'body') {
60 $self->{field_body} = $options{$name};
61 }
62 }
63 $self->{comment} = [];
64 }
65
66 =head1 CONSTRUCTORS
67
68 The following methods construct new C<Message::Field::Unstructured> objects:
69
70 =over 4
71
72 =item Message::Field::Structured->new ([%options])
73
74 Constructs a new C<Message::Field::Structured> object. You might pass some
75 options as parameters to the constructor.
76
77 =cut
78
79 sub new ($;%) {
80 my $class = shift;
81 my $self = bless {}, $class;
82 $self->_init (@_);
83 $self;
84 }
85
86 =item Message::Field::Structured->parse ($field-body, [%options])
87
88 Constructs a new C<Message::Field::Structured> object with
89 given field body. You might pass some options as parameters to the constructor.
90
91 =cut
92
93 sub parse ($$;%) {
94 my $class = shift;
95 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 $self;
100 }
101
102 =back
103
104 =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 $option{parse} = 1 if defined wantarray && !defined $option{parse};
125 $option{parse} = 1 if $option{parse_all} && !defined $option{parse};
126
127 ## Additional items
128 my $avalue;
129 for (@_) {
130 local $option{parse} = $option{parse};
131 my $ok;
132 ($ok, undef, $avalue) = $self->_add_array_check ($_, \%option);
133 if ($ok) {
134 $avalue = $self->_parse_value
135 ($option{_ARRAY_VALTYPE} => $avalue) if $option{parse};
136 if ($option{prepend}) {
137 unshift @{$self->{$array}}, $avalue;
138 } else {
139 push @{$self->{$array}}, $avalue;
140 }
141 }
142 }
143 $self->_add_return_value (\$avalue, \%option);
144 ## Return last added value if necessary.
145
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 Carp::croak (q{add: Method not available for this module});
155 }
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 $option{parse} = 1 if $option{parse_all} && !defined $option{parse};
164
165 ## Additional items
166 my $avalue;
167 while (my ($name => $value) = splice (@_, 0, 2)) {
168 next if $name =~ /^-/; $name =~ s/^\\//;
169 $name =~ tr/_/-/ if $option{translate_underscore};
170
171 my $ok;
172 local $option{parse} = $option{parse};
173 ($ok, $name, $avalue) = $self->_add_hash_check ($name => $value, \%option);
174 if ($ok) {
175 $avalue = $self->_parse_value ($name => $avalue) if $option{parse};
176 if ($option{prepend}) {
177 unshift @{$self->{$array}}, $avalue;
178 } else {
179 push @{$self->{$array}}, $avalue;
180 }
181 }
182 }
183 $self->_add_return_value (\$avalue, \%option);
184 ## Return last added value if necessary.
185 }
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 ## Returns returned item value \$item-value, \%option
195 sub _add_return_value ($\$\%) {
196 $_[1];
197 }
198
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 $option{parse} = 1 if defined wantarray && !defined $option{parse};
215 $option{parse} = 1 if $option{parse_all} && !defined $option{parse};
216
217 ## Additional items
218 my ($avalue, %replace);
219 for (@_) {
220 local $option{parse} = $option{parse};
221 my ($ok, $aname);
222 ($ok, $aname => $avalue)
223 = $self->_replace_array_check ($_, \%option);
224 if ($ok) {
225 $avalue = $self->_parse_value
226 ($option{_ARRAY_VALTYPE} => $avalue) if $option{parse};
227 $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 $self->_replace_return_value (\$avalue, \%option);
244 ## Return last added value if necessary.
245
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 Carp::croak (q{replace: Method not available for this module});
255 }
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 $option{parse} = 1 if $option{parse_all} && !defined $option{parse};
264
265 ## Additional items
266 my ($avalue, %replace);
267 while (my ($name => $value) = splice (@_, 0, 2)) {
268 next if $name =~ /^-/; $name =~ s/^\\//;
269 $name =~ tr/_/-/ if $option{translate_underscore};
270
271 my ($ok, $aname);
272 local $option{parse} = $option{parse};
273 ($ok, $aname => $avalue)
274 = $self->_replace_hash_check ($name => $value, \%option);
275 if ($ok) {
276 $avalue = $self->_parse_value ($name => $avalue) if $option{parse};
277 $replace{$aname} = $avalue;
278 }
279 }
280 for (@{$self->{$array}}) {
281 last unless keys %replace;
282 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 $self->_replace_return_value (\$avalue, \%option);
295 ## Return last added value if necessary.
296 }
297 }
298
299 ## $self->_replace_cleaning
300 ## -- Cleans the array/hash before replacing
301 sub _replace_cleaning ($) {
302 $_[0]->_delete_empty;
303 }
304 #*_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 sub _replace_array_check ($$\%) {
313 shift; 1, $_[0] => $_[0];
314 }
315
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 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
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 sub _replace_hash_check ($$$\%) {
333 shift; 1, $_[0] => [@_[0,1]];
334 }
335
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 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
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 sub _replace_return_value ($\$\%) {
353 $_[1];
354 }
355
356 ## TODO: Implement count by any and merge with item_exist
357 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 Carp::croak (q{count: Method not available for this module});
364 }
365 $self->_count_cleaning;
366 return $self->_count_by_name ($array => \%option) if defined $option{-name};
367 $#{$self->{$array}} + 1;
368 }
369
370 ## $self->_count_cleaning
371 ## -- Cleans the array/hash before counting
372 sub _count_cleaning ($) {
373 $_[0]->_delete_empty;
374 }
375
376 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 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 Carp::croak (q{delete: Method not available for this module});
393 }
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 ## 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 sub _delete_match ($$\$\%\%) {
416 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 }
426
427 sub _delete_cleaning ($) {
428 $_[0]->_delete_empty;
429 }
430
431 ## Delete empty items
432 sub _delete_empty ($) {
433 my $self = shift;
434 my $array = $self->{option}->{_ARRAY_NAME} || $self->{option}->{_HASH_NAME};
435 $self->{$array} = [grep {length $_} @{$self->{$array}}] if $array;
436 }
437
438 sub item ($$;%) {
439 my $self = shift;
440 my ($name, %p) = (shift, @_);
441 ## BUG: don't support -by
442 return $self->replace ($name => $p{-value}, @_) if defined $p{-value};
443 my %option = %{$self->{option}};
444 $option{new_item_unless_exist} = 1;
445 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 Carp::croak (q{item: Method not available for this module});
450 }
451 $option{parse} = 1 unless defined $option{parse};
452 $option{parse} = 1 if $option{parse_all} && !defined $option{parse};
453 my @r;
454 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 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 }
483
484 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 Carp::croak (q{item-exist: Method not available for this module});
493 }
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 ## 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 sub _item_match ($$\$\%\%) {
513 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 }
523
524 ## $value = $self->_item_return_value (\$item, \%option)
525 ## -- Returns returning value of item method
526 sub _item_return_value ($\$\%) {
527 $_[1];
528 }
529
530 ## $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 sub _item_new_value ($$\%) {
538 $_[1];
539 }
540
541 ## $self->_parse_value ($type, $value);
542 sub _parse_value ($$$) {
543 my $self = shift;
544 my $name = shift;
545 my $value = shift;
546 return $value if ref $value;
547 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 -body_default_charset => $self->{option}->{body_default_charset},
555 -body_default_charset_input => $self->{option}->{body_default_charset_input},
556 -format => $self->{option}->{format},
557 -field_ns => $self->{option}->{field_ns},
558 -field_name => $self->{option}->{field_name},
559 -field_param_name => $name,
560 -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 -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 if ($vtype eq ':none:') {
579 return $value;
580 } elsif (defined $value) {
581 eval "require $vtype" or Carp::croak (qq{<parse>: $vtype: Can't load package: $@});
582 return $vtype->parse ($value, %vopt);
583 } else {
584 eval "require $vtype" or Carp::croak (qq{<parse>: $vtype: Can't load package: $@});
585 return $vtype->new (%vopt);
586 }
587 }
588
589 ## 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 my $option = shift;
639 $option->{_comment_min} ||= 0;
640 $option->{_comment_max} = $#{$self->{comment}} unless defined $option->{_comment_max};
641 my @v;
642 for (@{$self->{comment}}[$option->{_comment_min}..$option->{_comment_max}]) {
643 push @v, '('. $self->Message::Util::encode_ccontent ($_) .')';
644 }
645 join ' ', @v;
646 }
647
648 sub scan ($&;%) {
649 my $self = shift;
650 my $sub = shift;
651 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 #my $sort = $option{sort};
661 #@param = sort $sort @param if ref $sort;
662 for my $param (@param) {
663 &$sub($self, $param, \%option);
664 }
665 }
666
667 sub _scan_sort ($\@) {
668 #my $self = shift;
669 @{$_[1]};
670 }
671
672 =head1 METHODS
673
674 =over 4
675
676 =item $self->stringify ([%options])
677
678 Returns field body as a string. Returned string is encoded,
679 quoted if necessary (by C<hook_encode_string>).
680
681 =cut
682
683 sub stringify ($;%) {
684 my $self = shift;
685 #$self->Message::Util::encode_qcontent ($self->{field_body});
686 $self->{field_body};
687 }
688 *as_string = \&stringify;
689
690 =item $self->as_plain_string
691
692 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
697 =cut
698
699 sub as_plain_string ($) {
700 my $self = shift;
701 my $s = $self->Message::Util::decode_qcontent ($self->{field_body});
702 Message::Util::unquote_quoted_string (Message::Util::unquote_ccontent ($s));
703 }
704
705 =item $self->option ( $option-name / $option-name, $option-value, ...)
706
707 If @_ == 1, returns option value. Else...
708
709 Set option value. You can pass multiple option name-value pair
710 as parameter. Example:
711
712 $msg->option (format => 'mail-rfc822',
713 capitalize => 0);
714 print $msg->option ('format'); ## mail-rfc822
715
716 =cut
717
718 sub option ($@) {
719 my $self = shift;
720 if (@_ == 1) {
721 return $self->{option}->{ $_[0] };
722 }
723 my %option = @_;
724 while (my ($name, $value) = splice (@_, 0, 2)) {
725 $self->{option}->{$name} = $value;
726 }
727 if ($option{-recursive}) {
728 $self->_option_recursive (\%option);
729 }
730 $self;
731 }
732
733 ## $self->_option_recursive (\%argv)
734 sub _option_recursive ($\%) {}
735
736 ## TODO: multiple value-type support
737 sub value_type ($;$$%) {
738 my $self = shift;
739 my $name = shift || $self->{option}->{_VALTYPE_DEFAULT};
740 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 || $self->{option}->{value_type}->{$self->{option}->{_VALTYPE_DEFAULT}}->[0];
749 } else {
750 $self->{option}->{value_type}->{$self->{option}->{_VALTYPE_DEFAULT}}->[0];
751 }
752 }
753
754 =item $self->clone ()
755
756 Returns a copy of Message::Field::Structured object.
757
758 =cut
759
760 sub clone ($) {
761 my $self = shift;
762 my $clone = ref($self)->new;
763 $clone->{option} = Message::Util::make_clone ($self->{option});
764 ## Common hash value (not used in this module)
765 $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 $clone;
773 }
774
775
776 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
787 =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 =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 =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 $Date: 2002/08/01 06:42:38 $
832
833 =cut
834
835 1;

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24