File Coverage

blib/lib/HTML/DOM/CharacterData.pm
Criterion Covered Total %
statement 107 107 100.0
branch 50 58 86.2
condition 15 21 71.4
subroutine 23 23 100.0
pod 12 15 80.0
total 207 224 92.4


line stmt bran cond sub pod time code
1             package HTML::DOM::CharacterData;
2              
3             # This contains those methods that are shared both by comments and text
4             # nodes.
5              
6 25     25   84 use warnings;
  25         27  
  25         641  
7 25     25   84 use strict;
  25         25  
  25         406  
8              
9 25     25   73 use HTML::DOM::Exception qw'INDEX_SIZE_ERR';
  25         29  
  25         843  
10 25     25   82 use Scalar::Util qw'blessed weaken';
  25         37  
  25         14704  
11              
12             require HTML::DOM::Node;
13              
14             our @ISA = 'HTML::DOM::Node';
15             our $VERSION = '0.057';
16              
17              
18             sub surrogify($);
19             sub desurrogify($);
20              
21              
22             # ~comment and ~text pseudo-elements (see HTML::Element) store the
23             # character data in the 'text' attribute.
24             sub data {
25 151     151 1 1448 my $old = (my $self = shift)->attr('text');
26 151 100       300 if(@_) {
27 20         59 $self->attr(text => my $strung = "$_[0]");
28 20         70 $self->_modified($old,$strung);
29             }
30             $old
31 151         760 }
32              
33             sub length {
34 1     1 1 3 length $_[0]->attr('text');
35             }
36              
37             sub length16 {
38 1     1 1 4 CORE::length surrogify $_[0]->attr('text');
39             }
40              
41             sub substringData { # obj, offset, length
42             # Throwing exceptions in these cases is really dumb, but what can I
43             # do? I'm trying to follow standards.
44 7     7 1 315 my($self,$off,$len) = @_;
45 7 100       30 die HTML::DOM::Exception->new(INDEX_SIZE_ERR,
46             'substringData cannot take a negative offset')
47             if $off <0;
48 5 50 66     20 die HTML::DOM::Exception->new(INDEX_SIZE_ERR,
49             'substringData cannot take a negative substring length')
50             if $len && $len <0;
51 5         16 my $text = $self->attr('text');
52 5 100       21 die HTML::DOM::Exception->new(INDEX_SIZE_ERR,
53             "substringData: $off is greater than the length of the text")
54             if $off > CORE::length $text;
55 3 100       18 defined $len ? substr( $text, $off, $len) : substr $text, $off, ;
56             }
57              
58             sub substringData16 { # obj, offset, length
59 8     8 1 353 my($self,$off,$len) = @_;
60 8 100       22 die HTML::DOM::Exception->new(INDEX_SIZE_ERR,
61             'substringData cannot take a negative offset')
62             if $off <0;
63 6 50 66     24 die HTML::DOM::Exception->new(INDEX_SIZE_ERR,
64             'substringData cannot take a negative substring length')
65             if $len && $len<0;
66 6         15 my $text = surrogify $self->attr('text');
67 6 100       24 die HTML::DOM::Exception->new(INDEX_SIZE_ERR,
68             "substringData: $off is greater than the length of the text")
69             if $off > CORE::length $text;
70 4 100       9 desurrogify defined $len
71             ? substr($text, $off, $len)
72             : substr $text, $off, ;
73             }
74              
75             sub appendData {
76 2     2 1 767 my $old = $_[0]->attr(text => my $new = $_[0]->attr('text').$_[1]);
77 2         6 $_[0]->_modified($old, $new);
78             return # nothing
79 2         7 }
80              
81             sub insertData { # obj, offset, string to insert
82 4     4 1 717 my ($self,$off,$insert) = @_;
83 4 100       16 die HTML::DOM::Exception->new(INDEX_SIZE_ERR,
84             'insertData cannot take a negative offset')
85             if $off <0;
86 3         8 my $text = $self->attr('text');
87 3 100       14 die HTML::DOM::Exception->new(INDEX_SIZE_ERR,
88             "insertData: $off is greater than the length of the text")
89             if $off > CORE::length $text;
90 2         6 substr($text, $off, 0) = $insert;
91 2         18 my $old = $self->attr(text => $text);
92 2         6 $self->_modified($old,$text);
93             return # nothing
94 2         7 }
95              
96             sub insertData16 { # obj, offset, string to insert
97 4     4 1 1015 my ($self,$off,$insert) = @_;
98 4 100       17 die HTML::DOM::Exception->new(INDEX_SIZE_ERR,
99             'insertData cannot take a negative offset')
100             if $off <0;
101 3         11 my $text = surrogify $self->attr('text');
102 3 100       13 die HTML::DOM::Exception->new(INDEX_SIZE_ERR,
103             "insertData: $off is greater than the length of the text")
104             if $off > CORE::length $text;
105 2         6 substr($text, $off, 0) = $insert;
106 2         6 my $old = $self->attr(text => desurrogify $text);
107 2         6 $self->_modified($old,$text);
108             return # nothing
109 2         7 }
110              
111             sub deleteData { # obj, offset, length
112 5     5 1 1017 my ($self,$off,$len) = @_;
113 5 100       16 die HTML::DOM::Exception->new(INDEX_SIZE_ERR,
114             'deleteData cannot take a negative offset')
115             if $off <0;
116 4 50 66     18 die HTML::DOM::Exception->new(INDEX_SIZE_ERR,
117             'deleteData cannot take a negative substring length')
118             if $len && $len <0;
119 4         11 my $text = $self->attr('text');
120 4 100       14 die HTML::DOM::Exception->new(INDEX_SIZE_ERR,
121             "deleteData: $off is greater than the length of the text")
122             if $off > CORE::length $text;
123 25     25   113 no warnings; # Silence nonsensical warnings
  25         32  
  25         3263  
124 3 100       17 undef(defined $len
125             ? substr( $text, $off, $len)
126             : substr $text, $off, );
127 3         9 my $old = $_[0]->attr(text => $text);
128 3         23 $self->_modified($old,$text);
129             return # nothing
130 3         10 }
131              
132             sub deleteData16 { # obj, offset, length
133 5     5 1 1043 my ($self,$off,$len) = @_;
134 5 100       19 die HTML::DOM::Exception->new(INDEX_SIZE_ERR,
135             'deleteData cannot take a negative offset')
136             if $off <0;
137 4 50 66     19 die HTML::DOM::Exception->new(INDEX_SIZE_ERR,
138             'deleteData cannot take a negative substring length')
139             if $len && $len <0;
140 4         11 my $text = surrogify $self->attr('text');
141 4 100       18 die HTML::DOM::Exception->new(INDEX_SIZE_ERR,
142             "deleteData: $off is greater than the length of the text")
143             if $off > CORE::length $text;
144 25     25   98 no warnings; # Silence nonsensical warnings
  25         27  
  25         6949  
145 3 100       14 undef( defined $len
146             ? substr( $text, $off, $len)
147             : substr $text, $off, );
148 3         8 my $old = $self->attr(text => desurrogify $text);
149 3         9 $self->_modified($old,$text);
150             return # nothing
151 3         10 }
152              
153             sub replaceData { # obj, offset, length, replacement
154 4     4 1 982 my ($self,$off,$len,$subst) = @_;
155 4 100       14 die HTML::DOM::Exception->new(INDEX_SIZE_ERR,
156             'replaceData cannot take a negative offset')
157             if $off <0;
158 3 50       8 die HTML::DOM::Exception->new(INDEX_SIZE_ERR,
159             'replaceData cannot take a negative substring length')
160             if $len <0;
161 3         8 my $text = $self->attr('text');
162 3 100       13 die HTML::DOM::Exception->new(INDEX_SIZE_ERR,
163             "replaceData: $off is greater than the length of the text")
164             if $off > CORE::length $text;
165 2         4 substr($text, $off, $len) = $subst;
166 2         5 my $old = $self->attr(text => $text);
167 2         5 $self->_modified($old,$text);
168             return # nothing
169 2         8 }
170              
171             sub replaceData16 { # obj, offset, length, replacement
172 4     4 0 1021 my ($self,$off,$len,$subst) = @_;
173 4 100       21 die HTML::DOM::Exception->new(INDEX_SIZE_ERR,
174             'replaceData cannot take a negative offset')
175             if $off <0;
176 3 50       7 die HTML::DOM::Exception->new(INDEX_SIZE_ERR,
177             'replaceData cannot take a negative substring length')
178             if $len <0;
179 3         9 my $text = surrogify $self->attr('text');
180 3 100       13 die HTML::DOM::Exception->new(INDEX_SIZE_ERR,
181             "replaceData: $off is greater than the length of the text")
182             if $off > CORE::length $text;
183 2         4 substr($text, $off, $len) = $subst;
184 2         5 my $old = $self->attr(text => desurrogify $text);
185 2         5 $self->_modified($old,$text);
186             return # nothing
187 2         8 }
188              
189             sub _modified {
190 36     36   38 my $self = shift;
191 36 50       159 $_[0] eq $_[1] or $self->trigger_event(
192             'DOMCharacterDataModified',
193             prev_value => $_[0],
194             new_value => $_[1],
195             );
196             };
197              
198             #------- UTILITY FUNCTIONS ---------#
199              
200             # ~~~ Should these be exported?
201              
202             sub surrogify($) { # copied straight from JE::String
203 17     17 0 16 my $ret = shift;
204              
205 25     25   113 no warnings 'utf8';
  25         38  
  25         4462  
206              
207 17         82 $ret =~ s<([^\0-\x{ffff}])><
208 13         84 chr((ord($1) - 0x10000) / 0x400 + 0xD800)
209             . chr((ord($1) - 0x10000) % 0x400 + 0xDC00)
210             >eg;
211 17         32 $ret;
212             }
213              
214             sub desurrogify($) { # copied straight from JE::String (with length changed
215             # to CORE::length)
216 11     11 0 13 my $ret = shift;
217 11         10 my($ord1, $ord2);
218 11         30 for(my $n = 0; $n < CORE::length $ret; ++$n) { # really slow
219 56 50 100     177 ($ord1 = ord substr $ret,$n,1) >= 0xd800 and
      66        
      66        
220             $ord1 <= 0xdbff and
221             ($ord2 = ord substr $ret,$n+1,1) >= 0xdc00 and
222             $ord2 <= 0xdfff and
223             substr($ret,$n,2) =
224             chr 0x10000 + ($ord1 - 0xD800) * 0x400 + ($ord2 - 0xDC00);
225             }
226              
227             # In perl 5.8.8, if there is a sub on the call stack that was
228             # triggered by the overloading mechanism when the object with the
229             # overloaded operator was passed as the only argument to 'die',
230             # then the following substitution magically calls that subroutine
231             # again with the same arguments, thereby causing infinite
232             # recursion:
233             #
234             # $ret =~ s/([\x{d800}-\x{dbff}])([\x{dc00}-\x{dfff}])/
235             # chr 0x10000 + (ord($1) - 0xD800) * 0x400 +
236             # (ord($2) - 0xDC00)
237             # /ge;
238             #
239             # 5.9.4 still has this bug.
240             # (fixed in 5.9.5--don't know which patch)
241              
242 11         48 $ret;
243             }
244              
245 5     5 1 23 sub nodeValue { $_[0]->data(@_[1..$#_]); }
246              
247              
248             1 __END__ 1
249              
250              
251             =head1 NAME
252              
253             HTML::DOM::CharacterData - A base class shared by HTML::DOM::Text and ::Comment
254              
255             =head1 VERSION
256              
257             Version 0.057
258              
259             =head1 DESCRIPTION
260              
261             This class provides those methods that are shared both by comments and text
262             nodes in an HTML DOM tree.
263              
264             =head1 METHODS
265              
266             =head2 Attributes
267              
268             The following DOM attributes are supported:
269              
270             =over 4
271              
272             =item data
273              
274             The textual data that the node contains.
275              
276             =item length
277              
278             The number of characters in C.
279              
280             =item length16
281              
282             A standards-compliant version of C that counts UTF-16 bytes instead
283             of characters.
284              
285             =back
286              
287             =head2 Other Methods
288              
289             =over 4
290              
291             =item substringData ( $offset, $length )
292              
293             Returns a substring of the data. If C<$length> is omitted, all characters
294             from C<$offset> to the end of the data are returned.
295              
296             =item substringData16
297              
298             A UTF-16 version of C.
299              
300             =item appendData ( $str )
301              
302             Appends C<$str> to the node's data.
303              
304             =item insertData ( $offset, $str )
305              
306             Inserts C<$str> at the given C<$offset>, which is understood to be the
307             number of Unicode characters from the beginning of the node's data.
308              
309             =item insertData16
310              
311             Like C, but C<$offset> is taken to be the number of UTF-16
312             (16-bit) bytes.
313              
314             =item deleteData ( $offset, $length )
315              
316             Deletes the specified data. If C<$length> is omitted, all characters from
317             C<$offset> to the end of the node's data are deleted.
318              
319             =item deleteData16
320              
321             A UTF-16 version of the above.
322              
323             =item replaceData ( $offset, $length, $str )
324              
325             This replaces the substring specified by C<$offset> and C<$length> with
326             C<$str>.
327              
328             =back
329              
330             =head1 SEE ALSO
331              
332             L
333              
334             L
335              
336             L