blib/lib/Dotiac/DTL/Filter.pm | |||
---|---|---|---|
Criterion | Covered | Total | % |
statement | 706 | 803 | 87.9 |
branch | 416 | 634 | 65.6 |
condition | 100 | 240 | 41.6 |
subroutine | 56 | 59 | 94.9 |
pod | 55 | 55 | 100.0 |
total | 1333 | 1791 | 74.4 |
line | stmt | bran | cond | sub | pod | time | code |
---|---|---|---|---|---|---|---|
1 | ############################################################################### | ||||||
2 | #Filter.pm | ||||||
3 | #Last Change: 2009-01-19 | ||||||
4 | #Copyright (c) 2009 Marc-Seabstian "Maluku" Lucksch | ||||||
5 | #Version 0.8 | ||||||
6 | #################### | ||||||
7 | #This file is part of the Dotiac::DTL project. | ||||||
8 | #http://search.cpan.org/perldoc?Dotiac::DTL | ||||||
9 | # | ||||||
10 | #Filter.pm is published under the terms of the MIT license, which basically | ||||||
11 | #means "Do with it whatever you want". For more information, see the | ||||||
12 | #license.txt file that should be enclosed with libsofu distributions. A copy of | ||||||
13 | #the license is (at the time of writing) also available at | ||||||
14 | #http://www.opensource.org/licenses/mit-license.php . | ||||||
15 | ############################################################################### | ||||||
16 | |||||||
17 | package Dotiac::DTL::Filter; | ||||||
18 | 12 | 12 | 57 | use strict; | |||
12 | 21 | ||||||
12 | 349 | ||||||
19 | 12 | 12 | 56 | use warnings; | |||
12 | 21 | ||||||
12 | 208331 | ||||||
20 | require Scalar::Util; | ||||||
21 | our $VERSION = 0.8; | ||||||
22 | |||||||
23 | sub add { | ||||||
24 | 24 | 24 | 1 | 27 | my $value=shift; | ||
25 | 24 | 25 | my $add=shift; | ||||
26 | 24 | 100 | 66 | 56 | $value->set($value->repr+$add->repr) if $value->number and $add->number; | ||
27 | 24 | 100 | 66 | 62 | $value->set($value->repr.$add->repr) unless $value->number and $add->number; | ||
28 | 24 | 62 | return $value; | ||||
29 | |||||||
30 | } | ||||||
31 | |||||||
32 | sub addslashes { | ||||||
33 | 8 | 8 | 1 | 9 | my $value =shift; | ||
34 | 8 | 21 | my $val=$value->repr(); | ||||
35 | 8 | 73 | $val=~s/([\\'"])/\\$1/g; | ||||
36 | 8 | 20 | $value->set($val); | ||||
37 | 8 | 19 | return $value; | ||||
38 | } | ||||||
39 | |||||||
40 | sub capfirst { | ||||||
41 | 8 | 8 | 1 | 8 | my $value=shift; | ||
42 | 8 | 17 | return $value->set(ucfirst $value->repr); | ||||
43 | } | ||||||
44 | |||||||
45 | sub center { | ||||||
46 | 16 | 16 | 1 | 17 | my $value=shift; | ||
47 | 16 | 17 | my $length=shift; | ||||
48 | 16 | 50 | 38 | return $value unless $length->number; | |||
49 | 16 | 15 | my $padding = shift; | ||||
50 | 16 | 18 | my $pad=" "; | ||||
51 | 16 | 100 | 34 | $pad=substr($padding->repr,0,1) if $padding; | |||
52 | 16 | 39 | my $val=$value->repr; | ||||
53 | 16 | 40 | my $len=$length->repr; | ||||
54 | 16 | 28 | $len-=CORE::length $val; | ||||
55 | 16 | 100 | 59 | $val=($pad x int($len/2)).$val.($pad x int($len/2)).($len%2?$pad:""); | |||
56 | 16 | 38 | $value->set($val); | ||||
57 | 16 | 35 | return $value; | ||||
58 | } | ||||||
59 | |||||||
60 | sub cut { | ||||||
61 | 24 | 24 | 1 | 33 | my $value=shift; | ||
62 | 24 | 65 | my $val=$value->repr(); | ||||
63 | 24 | 39 | my $t=shift; | ||||
64 | 24 | 58 | $t=$t->repr(); | ||||
65 | 24 | 281 | $val=~s/\Q$t//g; | ||||
66 | 24 | 76 | $value->set($val); | ||||
67 | 24 | 60 | return $value; | ||||
68 | } | ||||||
69 | |||||||
70 | #locale stuff | ||||||
71 | our @datemonths=qw( Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec ); | ||||||
72 | our @datemonthl=qw( January February March April May Juni Juli August September October November December ); | ||||||
73 | our @datemontha=qw( Jan. Feb. March April May Juni Juli Aug. Sep. Oct. Nov. Dec. ); | ||||||
74 | our @weekdays=qw/Sun Mon Tue Wed Thu Fri Sat/; | ||||||
75 | our @weekdayl=qw/Sunday Monday Tuesday Wednesday Thursday Friday Saturday/; | ||||||
76 | our @timeampm=qw/a.m. p.m. AM PM/; | ||||||
77 | our @timespotnames=qw/midnight noon/; | ||||||
78 | our @datesuffixes=qw/th st nd rd/; #qw/Default day1 day2 day3 day4 day5... | ||||||
79 | |||||||
80 | sub date { | ||||||
81 | 16 | 16 | 1 | 82 | my $value=shift; | ||
82 | 16 | 50 | 66 | 51 | return $value unless $value->number() or $value->array(); | ||
83 | 16 | 54 | my $time=$value->repr(); | ||||
84 | 16 | 36 | my $safe=0; | ||||
85 | 16 | 22 | my $string=shift; | ||||
86 | 16 | 50 | 33 | 76 | if (not defined $string or not $string->scalar()) { | ||
87 | 0 | 0 | $string=$Dotiac::DTL::DATE_FORMAT; | ||||
88 | 0 | 0 | $safe=1; | ||||
89 | } | ||||||
90 | else { | ||||||
91 | 16 | 49 | $safe=$string->safe(); | ||||
92 | 16 | 39 | $string=$string->repr; | ||||
93 | } | ||||||
94 | 16 | 31 | my @t; | ||||
95 | 16 | 100 | 39 | if ($value->number()) { | |||
96 | 12 | 45 | @t=localtime($time); | ||||
97 | } | ||||||
98 | else { | ||||||
99 | 4 | 5 | @t=@{$value->content}; | ||||
4 | 13 | ||||||
100 | } | ||||||
101 | 16 | 215 | my @s=split //,$string; | ||||
102 | 16 | 31 | my $res; | ||||
103 | 16 | 44 | while (my $s=shift(@s)) { | ||||
104 | 336 | 100 | 3427 | if ($s eq '\\') { | |||
100 | |||||||
100 | |||||||
100 | |||||||
100 | |||||||
100 | |||||||
100 | |||||||
100 | |||||||
100 | |||||||
100 | |||||||
100 | |||||||
100 | |||||||
100 | |||||||
100 | |||||||
100 | |||||||
100 | |||||||
100 | |||||||
100 | |||||||
100 | |||||||
100 | |||||||
100 | |||||||
100 | |||||||
100 | |||||||
100 | |||||||
100 | |||||||
100 | |||||||
50 | |||||||
50 | |||||||
100 | |||||||
100 | |||||||
100 | |||||||
100 | |||||||
50 | |||||||
50 | |||||||
50 | |||||||
100 | |||||||
50 | |||||||
50 | |||||||
105 | 8 | 21 | $res.=shift(@s); | ||||
106 | } | ||||||
107 | elsif ($s eq "a") { | ||||||
108 | 8 | 100 | 33 | 50 | if ($t[2] > 12 or ($t[2] == 12 and $t[1] > 0)) { | ||
66 | |||||||
109 | 4 | 13 | $res.=$timeampm[0]; | ||||
110 | } | ||||||
111 | else { | ||||||
112 | 4 | 19 | $res.=$timeampm[1]; | ||||
113 | } | ||||||
114 | } | ||||||
115 | elsif ($s eq "A") { | ||||||
116 | 8 | 100 | 33 | 214 | if ($t[2] > 12 or ($t[2] == 12 and $t[1] > 0)) { | ||
66 | |||||||
117 | 4 | 16 | $res.=$timeampm[2]; | ||||
118 | } | ||||||
119 | else { | ||||||
120 | 4 | 14 | $res.=$timeampm[3]; | ||||
121 | } | ||||||
122 | } | ||||||
123 | elsif ($s eq "b") { | ||||||
124 | 8 | 29 | $res.=lc($datemonths[$t[4]]); | ||||
125 | } | ||||||
126 | elsif ($s eq "d") { | ||||||
127 | 8 | 39 | $res.=sprintf("%02d",$t[3]); | ||||
128 | } | ||||||
129 | elsif ($s eq "D") { | ||||||
130 | 8 | 31 | $res.=$weekdays[$t[6]]; | ||||
131 | } | ||||||
132 | elsif ($s eq "f") { | ||||||
133 | 8 | 12 | my $h=$t[2]; | ||||
134 | 8 | 14 | $h=$h%12; | ||||
135 | 8 | 50 | 21 | $h=12 unless $h; | |||
136 | 8 | 13 | $res.=$h; | ||||
137 | 8 | 50 | 56 | $res.=sprintf(":%02d",$t[1]) if ($t[1]); | |||
138 | } | ||||||
139 | elsif ($s eq "F") { | ||||||
140 | 16 | 53 | $res.=$datemonthl[$t[4]]; | ||||
141 | } | ||||||
142 | elsif ($s eq "g") { | ||||||
143 | 8 | 12 | my $h=$t[2]; | ||||
144 | 8 | 10 | $h=$h%12; | ||||
145 | 8 | 50 | 28 | $h=12 unless $h; | |||
146 | 8 | 25 | $res.=$h; | ||||
147 | } | ||||||
148 | elsif ($s eq "G") { | ||||||
149 | 8 | 25 | $res.=$t[2]; | ||||
150 | } | ||||||
151 | elsif ($s eq "h") { | ||||||
152 | 8 | 14 | my $h=$t[2]; | ||||
153 | 8 | 10 | $h=$h%12; | ||||
154 | 8 | 50 | 19 | $h=12 unless $h; | |||
155 | 8 | 34 | $res.=sprintf("%02d",$h); | ||||
156 | } | ||||||
157 | elsif ($s eq "H") { | ||||||
158 | 16 | 57 | $res.=sprintf("%02d",$t[2]); | ||||
159 | } | ||||||
160 | elsif ($s eq "i") { | ||||||
161 | 16 | 58 | $res.=sprintf("%02d",$t[1]); | ||||
162 | } | ||||||
163 | elsif ($s eq "j") { | ||||||
164 | 16 | 54 | $res.=$t[3]; | ||||
165 | } | ||||||
166 | elsif ($s eq "l") { | ||||||
167 | 8 | 32 | $res.=$weekdayl[$t[6]]; | ||||
168 | } | ||||||
169 | elsif ($s eq "L") { | ||||||
170 | 8 | 17 | my $d=$t[5]+1900; | ||||
171 | 8 | 50 | 33 | 70 | $res.=(((not $d%4 and $d%100) or not $d%400)?"1":"0"); | ||
172 | } | ||||||
173 | elsif ($s eq "m") { | ||||||
174 | 8 | 34 | $res.=sprintf("%02d",$t[4]+1); | ||||
175 | } | ||||||
176 | elsif ($s eq "M") { | ||||||
177 | 8 | 25 | $res.=$datemonths[$t[4]]; | ||||
178 | } | ||||||
179 | elsif ($s eq "n") { | ||||||
180 | 8 | 28 | $res.=$t[4]+1; | ||||
181 | } | ||||||
182 | elsif ($s eq "N") { | ||||||
183 | 8 | 32 | $res.=$datemontha[$t[4]]; | ||||
184 | } | ||||||
185 | elsif ($s eq "O") { | ||||||
186 | 8 | 25 | my @tt=localtime(0); | ||||
187 | 8 | 50 | 57 | $tt[2]+=1 if $t[8]; | |||
188 | 8 | 43 | $res.=sprintf("%+05d",$tt[2]*100+$tt[1]); | ||||
189 | } | ||||||
190 | elsif ($s eq "P") { | ||||||
191 | 8 | 50 | 33 | 52 | if ($t[2] == 12 and $t[1] == 0) { | ||
50 | 33 | ||||||
192 | 0 | 0 | $res.=$timespotnames[1]; | ||||
193 | } | ||||||
194 | elsif ($t[2] == 0 and $t[1] == 0) { | ||||||
195 | 0 | 0 | $res.=$timespotnames[0]; | ||||
196 | } | ||||||
197 | else { | ||||||
198 | 8 | 13 | my $h=$t[2]; | ||||
199 | 8 | 11 | $h=$h%12; | ||||
200 | 8 | 50 | 19 | $h=12 unless $h; | |||
201 | 8 | 12 | $res.=$h; | ||||
202 | 8 | 50 | 30 | $res.=sprintf(":%02d",$t[1]) if ($t[1]); | |||
203 | 8 | 100 | 33 | 37 | if ($t[2] > 12 or ($t[2] == 12 and $t[1] > 0)) { | ||
66 | |||||||
204 | 4 | 16 | $res.=" ".$timeampm[0]; | ||||
205 | } | ||||||
206 | else { | ||||||
207 | 4 | 18 | $res.=" ".$timeampm[1]; | ||||
208 | } | ||||||
209 | } | ||||||
210 | |||||||
211 | } | ||||||
212 | elsif ($s eq "r") { | ||||||
213 | 8 | 16 | $res.=$weekdays[$t[6]]; | ||||
214 | 8 | 12 | $res.=", "; | ||||
215 | 8 | 13 | $res.=$t[4]+1; | ||||
216 | 8 | 22 | $res.=" ".$datemonths[$t[4]]." ".($t[5]+1900); | ||||
217 | 8 | 25 | $res.=sprintf(" %02d:%02d:%02d",$t[2],$t[1],$t[0]); | ||||
218 | 8 | 22 | my @tt=localtime(0); | ||||
219 | 8 | 50 | 50 | $tt[2]+=1 if $t[8]; | |||
220 | 8 | 37 | $res.=sprintf(" %+05d",$tt[2]*100+$tt[1]); | ||||
221 | } | ||||||
222 | elsif ($s eq "s") { | ||||||
223 | 8 | 31 | $res.=sprintf("%02d",$t[0]); | ||||
224 | } | ||||||
225 | elsif ($s eq "S") { | ||||||
226 | 16 | 100 | 36 | if ($datesuffixes[$t[3]]) { | |||
227 | 8 | 22 | $res.=$datesuffixes[$t[3]]; | ||||
228 | } | ||||||
229 | else { | ||||||
230 | 8 | 27 | $res.=$datesuffixes[0] | ||||
231 | } | ||||||
232 | } | ||||||
233 | elsif ($s eq "t") { | ||||||
234 | 8 | 50 | 33 | 175 | if ($t[4] == 1 or $t[4]==3 or $t[4] == 5 or $t[4] == 7 or $t[4] == 8 or $t[4] == 10 or $t[4] == 12) { | ||
50 | 33 | ||||||
33 | |||||||
33 | |||||||
33 | |||||||
33 | |||||||
235 | 0 | 0 | $res.="31"; | ||||
236 | } | ||||||
237 | elsif ($t[4] == 2) { | ||||||
238 | 0 | 0 | my $d=$t[5]+1900; | ||||
239 | 0 | 0 | 0 | 0 | if ((not $d%4 and $d%100) or not $d%400) { | ||
0 | |||||||
240 | 0 | 0 | $res.="29"; | ||||
241 | } | ||||||
242 | else { | ||||||
243 | 0 | 0 | $res.="28"; | ||||
244 | } | ||||||
245 | } | ||||||
246 | else { | ||||||
247 | 8 | 23 | $res.="30"; | ||||
248 | } | ||||||
249 | } | ||||||
250 | elsif ($s eq "T") { | ||||||
251 | 0 | 0 | require POSIX; | ||||
252 | 0 | 0 | $res.=POSIX::strftime("%Z", @t); | ||||
253 | } | ||||||
254 | elsif ($s eq "t") { | ||||||
255 | 0 | 0 | $res.=$t[6]; | ||||
256 | } | ||||||
257 | elsif ($s eq "W") { | ||||||
258 | 4 | 1103 | require POSIX; | ||||
259 | 4 | 8859 | $res.=POSIX::strftime("%W", @t); | ||||
260 | } | ||||||
261 | elsif ($s eq "y") { | ||||||
262 | 8 | 39 | $res.=sprintf("%02d",($t[5]%100)); | ||||
263 | } | ||||||
264 | elsif ($s eq "Y") { | ||||||
265 | 16 | 74 | $res.=sprintf("%04d",$t[5]+1900); | ||||
266 | } | ||||||
267 | elsif ($s eq "z") { | ||||||
268 | 8 | 30 | $res.=$t[7]; | ||||
269 | } | ||||||
270 | elsif ($s eq "Z") { | ||||||
271 | 0 | 0 | my @tt=localtime(0); | ||||
272 | 0 | 0 | 0 | $tt[2]+=1 if $t[8]; | |||
273 | 0 | 0 | $res.=$tt[2]*3600+$t[1]*60+$t[0]; | ||||
274 | } | ||||||
275 | elsif ($s eq "\n") { | ||||||
276 | 0 | 0 | $res.="n"; | ||||
277 | } | ||||||
278 | elsif ($s eq "\t") { | ||||||
279 | 0 | 0 | $res.="t"; | ||||
280 | } | ||||||
281 | elsif ($s eq "\f") { | ||||||
282 | 8 | 24 | $res.="f"; | ||||
283 | } | ||||||
284 | elsif ($s eq "\b") { | ||||||
285 | 0 | 0 | $res.="b"; | ||||
286 | } | ||||||
287 | elsif ($s eq "\r") { | ||||||
288 | 0 | 0 | $res.="r"; | ||||
289 | } | ||||||
290 | else { | ||||||
291 | 44 | 111 | $res.=$s; | ||||
292 | } | ||||||
293 | } | ||||||
294 | 16 | 65 | return Dotiac::DTL::Value->new($res,$safe); | ||||
295 | } | ||||||
296 | |||||||
297 | sub default { | ||||||
298 | 32 | 32 | 1 | 34 | my $val=shift; | ||
299 | 32 | 32 | my $def=shift; | ||||
300 | 32 | 50 | 67 | return $def unless $val->true; | |||
301 | 0 | 0 | return $val; | ||||
302 | } | ||||||
303 | |||||||
304 | sub default_if_none { | ||||||
305 | 12 | 12 | 1 | 14 | my $val=shift; | ||
306 | 12 | 11 | my $def=shift; | ||||
307 | 12 | 50 | 24 | return $def unless $val->defined; | |||
308 | 0 | 0 | return $val; | ||||
309 | } | ||||||
310 | |||||||
311 | sub dictsort { | ||||||
312 | 20 | 20 | 1 | 31 | my $value=shift; | ||
313 | 20 | 50 | 51 | return $value unless $value->array(); | |||
314 | 20 | 28 | my $by=shift; | ||||
315 | 20 | 100 | 35 | unless ($by) { | |||
316 | 64 | 100 | 66 | 193 | $value->set([sort { if (Scalar::Util::looks_like_number($a) and Scalar::Util::looks_like_number($b)) { | ||
8 | 21 | ||||||
317 | 40 | 49 | $a <=> $b | ||||
318 | } | ||||||
319 | else { | ||||||
320 | 24 | 48 | $a cmp $b | ||||
321 | } | ||||||
322 | 8 | 9 | } @{$value->content}]); | ||||
323 | 8 | 21 | return $value; | ||||
324 | } | ||||||
325 | 12 | 40 | $by=$by->repr(); | ||||
326 | 56 | 61 | $value->set([sort { | ||||
327 | 12 | 27 | my $aa = $a; | ||||
328 | 56 | 50 | 113 | if (ref $a) { | |||
329 | 56 | 100 | 66 | 255 | $aa = $a->{$by} if Scalar::Util::reftype($a) eq "HASH" and exists $a->{$by}; | ||
330 | 56 | 50 | 66 | 267 | $aa = $a->[$by] if Scalar::Util::reftype($a) eq "ARRAY" and Scalar::Util::looks_like_number($by) and exists $a->[$by]; | ||
66 | |||||||
331 | 56 | 50 | 33 | 133 | $aa = $a->$by() if Scalar::Util::blessed($a) and $a->can($by); | ||
332 | } | ||||||
333 | 56 | 61 | my $bb = $b; | ||||
334 | 56 | 50 | 109 | if (ref $b) { | |||
335 | 56 | 100 | 66 | 215 | $bb = $b->{$by} if Scalar::Util::reftype($b) eq "HASH" and $b->{$by}; | ||
336 | 56 | 50 | 66 | 234 | $bb = $b->[$by] if Scalar::Util::reftype($a) eq "ARRAY" and Scalar::Util::looks_like_number($by) and exists $b->[$by]; | ||
66 | |||||||
337 | 56 | 50 | 33 | 140 | $bb = $b->$by() if Scalar::Util::blessed($b) and $b->can($by); | ||
338 | } | ||||||
339 | 56 | 100 | 66 | 235 | if (Scalar::Util::looks_like_number($aa) and Scalar::Util::looks_like_number($bb)) { | ||
340 | 16 | 53 | $aa <=> $bb | ||||
341 | } | ||||||
342 | else { | ||||||
343 | 40 | 77 | $aa cmp $bb | ||||
344 | } | ||||||
345 | 12 | 24 | } @{$value->content}]); | ||||
346 | 12 | 31 | return $value; | ||||
347 | |||||||
348 | } | ||||||
349 | |||||||
350 | sub dictsortreversed { | ||||||
351 | 20 | 20 | 1 | 29 | my $value=shift; | ||
352 | 20 | 50 | 51 | return $value unless $value->array(); | |||
353 | 20 | 35 | my $by=shift; | ||||
354 | 20 | 100 | 36 | unless ($by) { | |||
355 | 64 | 100 | 66 | 230 | $value->set([reverse sort { if (Scalar::Util::looks_like_number($a) and Scalar::Util::looks_like_number($b)) { | ||
8 | 24 | ||||||
356 | 40 | 55 | $a <=> $b | ||||
357 | } | ||||||
358 | else { | ||||||
359 | 24 | 49 | $a cmp $b | ||||
360 | } | ||||||
361 | 8 | 12 | } @{$value->content}]); | ||||
362 | 8 | 23 | return $value; | ||||
363 | } | ||||||
364 | 12 | 57 | $by=$by->repr(); | ||||
365 | 56 | 56 | $value->set([reverse sort { | ||||
366 | 12 | 31 | my $aa = $a; | ||||
367 | 56 | 50 | 108 | if (ref $a) { | |||
368 | 56 | 100 | 66 | 240 | $aa = $a->{$by} if Scalar::Util::reftype($a) eq "HASH" and exists $a->{$by}; | ||
369 | 56 | 50 | 66 | 254 | $aa = $a->[$by] if Scalar::Util::reftype($a) eq "ARRAY" and Scalar::Util::looks_like_number($by) and exists $a->[$by]; | ||
66 | |||||||
370 | 56 | 50 | 33 | 141 | $aa = $a->$by() if Scalar::Util::blessed($a) and $a->can($by); | ||
371 | } | ||||||
372 | 56 | 62 | my $bb = $b; | ||||
373 | 56 | 50 | 94 | if (ref $b) { | |||
374 | 56 | 100 | 66 | 216 | $bb = $b->{$by} if Scalar::Util::reftype($b) eq "HASH" and $b->{$by}; | ||
375 | 56 | 50 | 66 | 254 | $bb = $b->[$by] if Scalar::Util::reftype($a) eq "ARRAY" and Scalar::Util::looks_like_number($by) and exists $b->[$by]; | ||
66 | |||||||
376 | 56 | 50 | 33 | 158 | $bb = $b->$by() if Scalar::Util::blessed($b) and $b->can($by); | ||
377 | } | ||||||
378 | 56 | 100 | 66 | 180 | if (Scalar::Util::looks_like_number($aa) and Scalar::Util::looks_like_number($bb)) { | ||
379 | 16 | 53 | $aa <=> $bb | ||||
380 | } | ||||||
381 | else { | ||||||
382 | 40 | 93 | $aa cmp $bb | ||||
383 | } | ||||||
384 | 12 | 18 | } @{$value->content}]); | ||||
385 | 12 | 33 | return $value; | ||||
386 | |||||||
387 | } | ||||||
388 | |||||||
389 | sub divisibleby { | ||||||
390 | 12 | 12 | 1 | 15 | my $value=shift; | ||
391 | 12 | 100 | 31 | return Dotiac::DTL::Value->safe(0) unless $value->number; | |||
392 | 8 | 10 | my $by=shift; | ||||
393 | 8 | 50 | 14 | return Dotiac::DTL::Value->safe(0) unless $by; | |||
394 | 8 | 50 | 16 | return Dotiac::DTL::Value->safe(0) unless $by->number; | |||
395 | 8 | 18 | my $res=!($value->content % $by->content); | ||||
396 | 8 | 23 | return Dotiac::DTL::Value->safe($res); | ||||
397 | } | ||||||
398 | |||||||
399 | sub escape { | ||||||
400 | 72 | 72 | 1 | 104 | my $value=shift; | ||
401 | 72 | 280 | $value->escape(1); | ||||
402 | 72 | 180 | return $value; | ||||
403 | } | ||||||
404 | |||||||
405 | #Not for JSON output of objects, I need to write an JSON-Addon for that. | ||||||
406 | |||||||
407 | my %jsescape = ( | ||||||
408 | "\n" => "\\n", | ||||||
409 | "\r" => "\\r", | ||||||
410 | "\t" => "\\t", | ||||||
411 | "\f" => "\\f", | ||||||
412 | "\b" => "\\b", | ||||||
413 | '"' => "\\\"", | ||||||
414 | "\\" => "\\\\", | ||||||
415 | "'" => "\\'", | ||||||
416 | ); | ||||||
417 | |||||||
418 | sub escapejs { | ||||||
419 | 12 | 12 | 1 | 15 | my $value=shift; | ||
420 | 12 | 32 | my $val=$value->repr(); | ||||
421 | 12 | 44 | $val =~ s/([\n\r\t\f\b"'\\])/$jsescape{$1}/eg; | ||||
20 | 65 | ||||||
422 | #$val =~ s/([\x00-\x08\x0b\x0e-\x1f\x7f-\x{FFFF}])/'\\u' .sprintf("%04x",ord($1))/eg; #Won't work in Perl 5.6.0 | ||||||
423 | 12 | 36 | $val =~ s/([^\x09\x0a\x0c\x0d\x20-\x7e])/'\\u' .sprintf("%04x",ord($1))/eg; | ||||
8 | 34 | ||||||
424 | 12 | 32 | $value->set($val); | ||||
425 | 12 | 37 | return $value; | ||||
426 | } | ||||||
427 | |||||||
428 | #Locale crap | ||||||
429 | our @filesizeformat=qw/bytes Kb Mb Gb Tb Eb Pb manybytes manybytes manybytes manybytes/; | ||||||
430 | |||||||
431 | our $floatformatlocale=""; | ||||||
432 | #sub { | ||||||
433 | # my $v=shift; | ||||||
434 | # $v=s/\./,/g; | ||||||
435 | # return $v; | ||||||
436 | #} | ||||||
437 | |||||||
438 | sub filesizeformat { | ||||||
439 | 12 | 12 | 1 | 14 | my $val=shift; | ||
440 | 12 | 50 | 28 | return $val unless $val->number(); | |||
441 | 12 | 30 | my $value=$val->content(); | ||||
442 | 12 | 14 | my $i=0; | ||||
443 | 12 | 24 | while ($value >= 1024.0) { | ||||
444 | 24 | 23 | $value=$value/1024.0; | ||||
445 | 24 | 39 | $i++; | ||||
446 | } | ||||||
447 | 12 | 100 | 21 | if ($value < 10) { | |||
448 | 8 | 46 | $value=sprintf("%1.2f",$value); | ||||
449 | } | ||||||
450 | else { | ||||||
451 | 4 | 20 | $value=sprintf("%4.1f",$value); | ||||
452 | } | ||||||
453 | 12 | 27 | $value=~s/0+$//g; | ||||
454 | 12 | 21 | $value=~s/\.$//g; | ||||
455 | 12 | 50 | 19 | $value=$floatformatlocale->($value) if $floatformatlocale; | |||
456 | 12 | 53 | $val->set($value." ".$filesizeformat[$i]); | ||||
457 | 12 | 31 | return $val; | ||||
458 | } | ||||||
459 | |||||||
460 | sub first { | ||||||
461 | 12 | 12 | 1 | 14 | my $value=shift; | ||
462 | 12 | 50 | 29 | if ($value->object) { | |||
463 | 0 | 0 | 0 | if ($value->content->can("__getitem__")) { | |||
464 | 0 | 0 | my $x = $value->content->__getitem__(0); | ||||
465 | 0 | 0 | 0 | if (defined $x) { | |||
466 | 0 | 0 | $value->set($x); | ||||
467 | 0 | 0 | return $value; | ||||
468 | } | ||||||
469 | } | ||||||
470 | } | ||||||
471 | 12 | 100 | 30 | if ($value->array) { | |||
50 | |||||||
472 | 8 | 22 | $value->set($value->content->[0]); | ||||
473 | } | ||||||
474 | elsif ($value->hash) { | ||||||
475 | 4 | 6 | my @a=sort keys %{$value->content}; | ||||
4 | 10 | ||||||
476 | 4 | 12 | $value->set($value->content->{$a[0]}); | ||||
477 | } | ||||||
478 | 12 | 38 | return $value; | ||||
479 | } | ||||||
480 | |||||||
481 | sub fix_ampersands { | ||||||
482 | 12 | 12 | 1 | 12 | my $value=shift; | ||
483 | 12 | 26 | my $val=$value->repr(); | ||||
484 | 12 | 32 | $val=~s/&/&/g; | ||||
485 | 12 | 29 | $value->set($val); | ||||
486 | 12 | 24 | return $value; | ||||
487 | } | ||||||
488 | |||||||
489 | sub floatformat { | ||||||
490 | 16 | 16 | 1 | 19 | my $val=shift; | ||
491 | 16 | 50 | 40 | return $val if not $val->number; | |||
492 | 16 | 42 | my $value=$val->content; | ||||
493 | 16 | 20 | my $arg=shift; | ||||
494 | 16 | 100 | 100 | 55 | if ($arg and not $arg->number) { | ||
495 | 4 | 18 | $val->set(int($value+0.5)); | ||||
496 | 4 | 12 | return $val | ||||
497 | } | ||||||
498 | 12 | 100 | 22 | if ($arg) { | |||
499 | 8 | 15 | $arg=$arg->content; | ||||
500 | } | ||||||
501 | else { | ||||||
502 | 4 | 5 | $arg=-1; | ||||
503 | } | ||||||
504 | 12 | 34 | my $skip=$arg=~s/^-//; | ||||
505 | 12 | 79 | $value=sprintf("%.".$arg."f",$value); | ||||
506 | 12 | 100 | 25 | unless ($skip) { | |||
507 | 8 | 50 | 15 | $value=$floatformatlocale->($value) if $floatformatlocale; | |||
508 | 8 | 21 | $val->set($value); | ||||
509 | 8 | 21 | return $val; | ||||
510 | } | ||||||
511 | 4 | 16 | $value=~s/0+$//g; | ||||
512 | 4 | 9 | $value=~s/\.$//g; | ||||
513 | 4 | 50 | 11 | $value=$floatformatlocale->($value) if $floatformatlocale; | |||
514 | 4 | 12 | $val->set($value); | ||||
515 | 4 | 10 | return $val; | ||||
516 | } | ||||||
517 | |||||||
518 | my $escape=sub { | ||||||
519 | my $val=shift; | ||||||
520 | $val=~s/&/&/g; | ||||||
521 | $val=~s/</g; | ||||||
522 | $val=~s/>/>/g; | ||||||
523 | $val=~s/\"/"/g; | ||||||
524 | $val=~s/\'/'/g; | ||||||
525 | return $val; | ||||||
526 | }; | ||||||
527 | |||||||
528 | sub force_escape { | ||||||
529 | 12 | 12 | 1 | 16 | my $value=shift; | ||
530 | 12 | 37 | $value->escape(1); | ||||
531 | 12 | 30 | return Dotiac::DTL::Value->safe($value->string()); | ||||
532 | } | ||||||
533 | |||||||
534 | sub get_digit { | ||||||
535 | 12 | 12 | 1 | 15 | my $value=shift; | ||
536 | 12 | 100 | 32 | return $value unless $value->number; | |||
537 | 8 | 21 | my $val=$value->content;; | ||||
538 | 8 | 11 | my $pos = shift; | ||||
539 | 8 | 50 | 33 | 28 | return $val unless defined $pos and $pos->number; | ||
540 | 8 | 17 | $pos=int $pos->content; | ||||
541 | 8 | 50 | 17 | return $value if $pos < 1; | |||
542 | 8 | 100 | 24 | return Dotiac::DTL::Value->safe(0) if $pos > CORE::length($val); | |||
543 | 4 | 18 | $value->set(substr $val,-$pos,1); | ||||
544 | 4 | 12 | return $value; | ||||
545 | } | ||||||
546 | |||||||
547 | #Should only be used together with urlencode | ||||||
548 | sub iriencode { | ||||||
549 | 12 | 12 | 1 | 14 | my $val=shift; | ||
550 | 12 | 31 | my $value=$val->repr; | ||||
551 | #require Encode; | ||||||
552 | #$value=Encode::encode_utf8($value) if Encode::is_utf8($value); | ||||||
553 | 12 | 33 | 17 | $value = eval { pack("C*", unpack("U0C*", $value))} || pack("C*", unpack("C*", $value)); | |||
554 | 12 | 37 | $value=~s/([^a-zA-Z0-9\[\]\(\)\$\%\&\/:;#=,!\?\*_.~-])/uc sprintf("%%%02x",ord($1))/eg; | ||||
16 | 65 | ||||||
555 | 12 | 31 | $val->set($value); | ||||
556 | 12 | 27 | return $val; | ||||
557 | } | ||||||
558 | |||||||
559 | sub join { | ||||||
560 | 20 | 20 | 1 | 30 | my $value=shift; | ||
561 | 20 | 23 | my $j=shift; | ||||
562 | 20 | 100 | 42 | if ($j) { | |||
563 | 16 | 47 | $j=$j->repr; | ||||
564 | } | ||||||
565 | else { | ||||||
566 | 4 | 6 | $j=""; | ||||
567 | } | ||||||
568 | 20 | 50 | 69 | if ($value->object) { | |||
569 | 0 | 0 | 0 | 0 | if ($value->content->can("__len__") and $value->content->can("__getitem__")) { #No support for __iter__ right now. | ||
570 | 0 | 0 | my @a; | ||||
571 | 0 | 0 | foreach my $i (0 .. $value->content->__len__()-1) { | ||||
572 | 0 | 0 | push @a,$value->content->__getitem__($i); | ||||
573 | } | ||||||
574 | 0 | 0 | $value->set(CORE::join($j,@a)); | ||||
575 | 0 | 0 | return $value | ||||
576 | } | ||||||
577 | 0 | 0 | 0 | 0 | if ($value->content->can("count") and $value->content->can("__getitem__")) { #No support for __iter__ right now. | ||
578 | 0 | 0 | my @a; | ||||
579 | 0 | 0 | foreach my $i (0 .. $value->content->count()-1) { | ||||
580 | 0 | 0 | push @a,$value->content->__getitem__($i); | ||||
581 | } | ||||||
582 | 0 | 0 | $value->set(CORE::join($j,@a)); | ||||
583 | 0 | 0 | return $value; | ||||
584 | } | ||||||
585 | } | ||||||
586 | 20 | 50 | 55 | $value->set(CORE::join($j,@{$value->content})) if $value->array; | |||
20 | 58 | ||||||
587 | 20 | 50 | 65 | $value->set(CORE::join($j,values %{$value->content})) if $value->hash; | |||
0 | 0 | ||||||
588 | 20 | 55 | return $value; | ||||
589 | } | ||||||
590 | |||||||
591 | sub last { | ||||||
592 | 12 | 12 | 1 | 16 | my $value=shift; | ||
593 | 12 | 50 | 31 | if ($value->object) { | |||
594 | 0 | 0 | 0 | 0 | if ($value->content->can("__len__") and $value->content->can("__getitem__")) { | ||
595 | 0 | 0 | my $x = $value->content->__getitem__($value->content->__len__()-1); | ||||
596 | 0 | 0 | 0 | if (defined $x) { | |||
597 | 0 | 0 | $value->set($x); | ||||
598 | 0 | 0 | return $value; | ||||
599 | } | ||||||
600 | } | ||||||
601 | 0 | 0 | 0 | 0 | if ($value->content->can("count") and $value->content->can("__getitem__")) { | ||
602 | 0 | 0 | my $x = $value->content->__getitem__($value->content->count()-1); | ||||
603 | 0 | 0 | 0 | if (defined $x) { | |||
604 | 0 | 0 | $value->set($x); | ||||
605 | 0 | 0 | return $value; | ||||
606 | } | ||||||
607 | } | ||||||
608 | } | ||||||
609 | 12 | 100 | 35 | if ($value->array) { | |||
50 | |||||||
610 | 8 | 100 | 9 | if (@{$value->content}) { | |||
8 | 27 | ||||||
611 | 4 | 11 | $value->set($value->content->[-1]); | ||||
612 | } | ||||||
613 | else { | ||||||
614 | 4 | 11 | $value->set(undef); | ||||
615 | } | ||||||
616 | } | ||||||
617 | elsif ($value->hash) { | ||||||
618 | 4 | 4 | my @a=sort keys %{$value->content}; | ||||
4 | 11 | ||||||
619 | 4 | 50 | 10 | if (@a) { | |||
620 | 4 | 10 | $value->set($value->content->{$a[-1]}); | ||||
621 | } | ||||||
622 | else { | ||||||
623 | 0 | 0 | $value->set(undef); | ||||
624 | } | ||||||
625 | } | ||||||
626 | 12 | 38 | return $value; | ||||
627 | } | ||||||
628 | |||||||
629 | sub length { | ||||||
630 | 12 | 12 | 1 | 13 | my $value=shift; | ||
631 | 12 | 50 | 29 | return Dotiac::DTL::Value->safe(0) if $value->undef; | |||
632 | 12 | 100 | 31 | return Dotiac::DTL::Value->safe(CORE::length($value->content)) if $value->scalar; | |||
633 | 8 | 50 | 33 | 18 | return Dotiac::DTL::Value->safe($value->content->count()) if $value->object and $value->content->can("count"); | ||
634 | 8 | 50 | 33 | 16 | return Dotiac::DTL::Value->safe($value->content->__len__()) if $value->object and $value->content->can("__len__"); | ||
635 | 8 | 100 | 18 | return Dotiac::DTL::Value->safe(scalar @{$value->content}) if $value->array; | |||
4 | 11 | ||||||
636 | 4 | 50 | 11 | return Dotiac::DTL::Value->safe(scalar keys %{$value->content}) if $value->hash; | |||
4 | 10 | ||||||
637 | 0 | 0 | return Dotiac::DTL::Value->safe(0); | ||||
638 | } | ||||||
639 | |||||||
640 | #output will be 1 or 0, not True or False | ||||||
641 | sub length_is { | ||||||
642 | 12 | 12 | 1 | 13 | my $value=shift; | ||
643 | 12 | 11 | my $is=shift; | ||||
644 | 12 | 50 | 28 | if ($is->number) { | |||
645 | 12 | 26 | $is=int($is->content()); | ||||
646 | } | ||||||
647 | else { | ||||||
648 | 0 | 0 | $is=0; | ||||
649 | } | ||||||
650 | 12 | 50 | 33 | 54 | $is = 0 unless defined $is and Scalar::Util::looks_like_number($is); | ||
651 | 12 | 50 | 26 | return Dotiac::DTL::Value->safe(!$is) if $value->undef; | |||
652 | 12 | 100 | 29 | return Dotiac::DTL::Value->safe(CORE::length($value->content) == $is) if $value->scalar(); | |||
653 | 8 | 50 | 33 | 20 | return Dotiac::DTL::Value->safe($value->content->count() == $is) if $value->object and $value->content->can("count"); | ||
654 | 8 | 50 | 33 | 21 | return Dotiac::DTL::Value->safe($value->content->__len__() == $is) if $value->object and $value->content->can("__len__"); | ||
655 | 8 | 100 | 18 | return Dotiac::DTL::Value->safe(@{$value->content} == $is) if $value->array; | |||
4 | 11 | ||||||
656 | 4 | 50 | 10 | return Dotiac::DTL::Value->safe(keys %{$value->content} == $is) if $value->hash; | |||
4 | 10 | ||||||
657 | 0 | 0 | return Dotiac::DTL::Value->safe(0) | ||||
658 | } | ||||||
659 | |||||||
660 | sub linebreaks { | ||||||
661 | 12 | 12 | 1 | 20 | my $value=shift; | ||
662 | 12 | 27 | $value=$value->string(); | ||||
663 | 12 | 56 | $value=~s/\n\s*\n/<\/p> /g; |
||||
664 | 12 | 30 | $value=~s/\n/ /g; |
||||
665 | 12 | 44 | return Dotiac::DTL::Value->safe(" ".$value." "); |
||||
666 | } | ||||||
667 | |||||||
668 | sub linebreaksbr { | ||||||
669 | 12 | 12 | 1 | 14 | my $value=shift; | ||
670 | 12 | 27 | $value=$value->string(); | ||||
671 | 12 | 39 | $value=~s/\n/ /g; |
||||
672 | 12 | 32 | return Dotiac::DTL::Value->safe($value); | ||||
673 | } | ||||||
674 | |||||||
675 | sub linenumbers { | ||||||
676 | 12 | 12 | 1 | 15 | my $val=shift; | ||
677 | 12 | 29 | my $value=$val->repr(); | ||||
678 | 12 | 50 | 27 | return $val->set("1: $value") unless $value; | |||
679 | 12 | 22 | my $count = ($value =~ tr/\n/\n/); | ||||
680 | 12 | 16 | $count=CORE::length $count; | ||||
681 | 12 | 10 | my $i=1; | ||||
682 | 12 | 32 | $value=~s/\n/sprintf("\n%0$count"."d: ",++$i)/eg; | ||||
44 | 112 | ||||||
683 | 12 | 46 | return $val->set(sprintf("%0$count"."d: ",1).$value); | ||||
684 | } | ||||||
685 | |||||||
686 | sub ljust { | ||||||
687 | 16 | 16 | 1 | 22 | my $value=shift; | ||
688 | 16 | 16 | my $length=shift; | ||||
689 | 16 | 50 | 41 | return $value unless $length->number; | |||
690 | 16 | 19 | my $padding = shift; | ||||
691 | 16 | 19 | my $pad=" "; | ||||
692 | 16 | 100 | 32 | $pad=substr($padding->repr,0,1) if $padding; | |||
693 | 16 | 35 | my $val=$value->repr; | ||||
694 | 16 | 40 | my $len=$length->repr; | ||||
695 | 16 | 30 | $len-=CORE::length $val; | ||||
696 | 16 | 23 | $val=$val.($pad x int($len)); | ||||
697 | 16 | 37 | $value->set($val); | ||||
698 | 16 | 36 | return $value; | ||||
699 | } | ||||||
700 | |||||||
701 | sub lower { | ||||||
702 | 44 | 44 | 1 | 64 | my $value=shift; | ||
703 | 44 | 137 | return $value->set(lc $value->repr); | ||||
704 | } | ||||||
705 | |||||||
706 | sub make_list { | ||||||
707 | 20 | 20 | 1 | 28 | my $value=shift; | ||
708 | 20 | 56 | my $val=$value->repr; | ||||
709 | 20 | 33 | my $by=shift; | ||||
710 | 20 | 100 | 46 | if ($by) { | |||
711 | 4 | 14 | $by=quotemeta $by->repr; | ||||
712 | 4 | 42 | $value->set([split /$by/,$val]); | ||||
713 | } | ||||||
714 | 20 | 111 | return $value->set([split //,$val]); | ||||
715 | } | ||||||
716 | |||||||
717 | #No locale for now | ||||||
718 | |||||||
719 | sub phone2numeric { | ||||||
720 | 12 | 12 | 1 | 17 | my $val=shift; | ||
721 | 12 | 37 | my $value=$val->repr; | ||||
722 | 12 | 28 | $value=~y/AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpRrSsTtUuVvWwXxYy/222222333333444444555555666666777777888888999999/; | ||||
723 | 12 | 37 | return $val->set($value); | ||||
724 | } | ||||||
725 | |||||||
726 | our $pluralizedefault = "s"; | ||||||
727 | |||||||
728 | sub pluralize { | ||||||
729 | 32 | 32 | 1 | 49 | my $value=shift; | ||
730 | 32 | 246 | my $val=0; | ||||
731 | 32 | 50 | 89 | $val=CORE::length $value->content if $value->scalar; | |||
732 | 32 | 50 | 189 | $val=$value->content if $value->number; | |||
733 | 32 | 50 | 133 | $val=scalar keys %{$value->content} if $value->hash; | |||
0 | 0 | ||||||
734 | 32 | 50 | 239 | $val=scalar @{$value->content} if $value->array; | |||
0 | 0 | ||||||
735 | 32 | 52 | my $s = $pluralizedefault; | ||||
736 | 32 | 100 | 76 | if (@_) { | |||
737 | 24 | 50 | 60 | $s=shift() if @_; | |||
738 | 24 | 71 | $s=$s->repr(); | ||||
739 | } | ||||||
740 | 32 | 261 | my $p; | ||||
741 | my $o; | ||||||
742 | 32 | 100 | 64 | if (@_) { | |||
743 | 8 | 15 | $o=$s; | ||||
744 | 8 | 13 | $p=shift; | ||||
745 | 8 | 220 | $p=$p->repr(); | ||||
746 | } | ||||||
747 | else { | ||||||
748 | 24 | 65 | ($o,$p) = split /,/,$s,2; | ||||
749 | } | ||||||
750 | 32 | 100 | 75 | unless ($p) { | |||
751 | 16 | 22 | $p=$o; | ||||
752 | 16 | 21 | $o=""; | ||||
753 | } | ||||||
754 | 32 | 100 | 123 | return $value->set($val==1?$o:$p); | |||
755 | } | ||||||
756 | |||||||
757 | |||||||
758 | sub pprint { | ||||||
759 | 0 | 0 | 1 | 0 | require Data::Dumper; | ||
760 | 0 | 0 | return Dotiac::DTL::Value->new(Data::Dumper->Dump([@_])); | ||||
761 | } | ||||||
762 | |||||||
763 | sub random { | ||||||
764 | 12 | 12 | 1 | 14 | my $value=shift; | ||
765 | 12 | 50 | 36 | if ($value->object) { | |||
766 | 0 | 0 | 0 | 0 | if ($value->content->can("__len__") and $value->content->can("__getitem__")) { | ||
767 | 0 | 0 | my $x = $value->content->__getitem__(int(rand($value->content->__len__()))); | ||||
768 | 0 | 0 | 0 | if (defined $x) { | |||
769 | 0 | 0 | return $value->set($x); | ||||
770 | } | ||||||
771 | } | ||||||
772 | 0 | 0 | 0 | 0 | if ($value->content->can("count") and $value->content->can("__getitem__")) { | ||
773 | 0 | 0 | my $x = $value->content->__getitem__(int(rand($value->content->count()))); | ||||
774 | 0 | 0 | 0 | if (defined $x) { | |||
775 | 0 | 0 | return $value->set($x); | ||||
776 | } | ||||||
777 | } | ||||||
778 | } | ||||||
779 | 12 | 100 | 35 | if ($value->array) { | |||
50 | |||||||
780 | 8 | 100 | 8 | if (@{$value->content}) { | |||
8 | 21 | ||||||
781 | 4 | 11 | return $value->set($value->content->[int(rand(scalar @{$value->content}))]); | ||||
4 | 12 | ||||||
782 | } | ||||||
783 | else { | ||||||
784 | 4 | 11 | return $value->set(undef); | ||||
785 | } | ||||||
786 | } | ||||||
787 | elsif ($value->hash) { | ||||||
788 | 4 | 6 | my @a=sort keys %{$value->content}; | ||||
4 | 12 | ||||||
789 | 4 | 50 | 11 | if (@a) { | |||
790 | 4 | 10 | return $value->set($value->content->{$a[int(rand(scalar @a))]}); | ||||
791 | } | ||||||
792 | else { | ||||||
793 | 0 | 0 | return $value->set(undef); | ||||
794 | } | ||||||
795 | } | ||||||
796 | 0 | 0 | return $value; | ||||
797 | } | ||||||
798 | |||||||
799 | sub removetags { | ||||||
800 | 12 | 12 | 1 | 17 | my $val=shift; | ||
801 | 12 | 31 | my $value=$val->repr(); | ||||
802 | 12 | 20 | my $tags=shift; | ||||
803 | 12 | 26 | $tags=$tags->repr; | ||||
804 | 12 | 50 | 27 | if ($tags) { | |||
805 | 12 | 34 | my @t=split /\s+/,$tags; | ||||
806 | 12 | 20 | my $t=CORE::join("|",map {quotemeta $_} @t); | ||||
20 | 48 | ||||||
807 | 12 | 443 | $value=~s/<\/?(?:$t)(?:\/?>|\s[^>]+>)//g; | ||||
808 | } | ||||||
809 | 12 | 43 | return $val->set($value); | ||||
810 | } | ||||||
811 | |||||||
812 | sub rjust { | ||||||
813 | 16 | 16 | 1 | 20 | my $value=shift; | ||
814 | 16 | 17 | my $length=shift; | ||||
815 | 16 | 50 | 46 | return $value unless $length->number; | |||
816 | 16 | 20 | my $padding = shift; | ||||
817 | 16 | 21 | my $pad=" "; | ||||
818 | 16 | 100 | 37 | $pad=substr($padding->repr,0,1) if $padding; | |||
819 | 16 | 41 | my $val=$value->repr; | ||||
820 | 16 | 43 | my $len=$length->repr; | ||||
821 | 16 | 31 | $len-=CORE::length $val; | ||||
822 | 16 | 34 | $val=($pad x int($len)).$val; | ||||
823 | 16 | 43 | $value->set($val); | ||||
824 | 16 | 42 | return $value; | ||||
825 | } | ||||||
826 | |||||||
827 | sub safe { | ||||||
828 | 36 | 36 | 1 | 52 | my $value=shift; | ||
829 | 36 | 103 | $value->safe(1); | ||||
830 | 36 | 84 | return $value; | ||||
831 | } | ||||||
832 | |||||||
833 | sub slice { | ||||||
834 | 40 | 40 | 1 | 50 | my $value=shift; | ||
835 | 40 | 50 | 66 | 97 | return $value unless $value->hash or $value->array; | ||
836 | 40 | 67 | my $slice=shift; | ||||
837 | 40 | 50 | 70 | return $value unless $slice; | |||
838 | 40 | 130 | $slice=$slice->repr; | ||||
839 | 40 | 118 | my @slice=split /:/,$slice,2; | ||||
840 | |||||||
841 | 40 | 179 | my @value; | ||||
842 | 40 | 100 | 100 | @value=@{$value->content} if $value->array; | |||
20 | 54 | ||||||
843 | 40 | 100 | 103 | @value=sort keys %{$value->content} if $value->hash; | |||
20 | 51 | ||||||
844 | |||||||
845 | 40 | 100 | 167 | $slice[0] = int($slice[0] || 0) || 0; | |||
846 | 40 | 100 | 86 | unless ($#slice) { | |||
847 | 8 | 50 | 26 | return $value unless Scalar::Util::looks_like_number($slice[0]); | |||
848 | 8 | 100 | 22 | return $value->set($value[int($slice[0])]) if $value->array; | |||
849 | 4 | 50 | 16 | return $value->set($value->content->{$value[int($slice[0])]}) if $value->hash; | |||
850 | } | ||||||
851 | |||||||
852 | 32 | 100 | 119 | $slice[1] = int($slice[1] || 0) || 0; | |||
853 | 32 | 100 | 66 | $slice[1]-=$slice[0] if ($slice[1] > 0); | |||
854 | 32 | 100 | 69 | $slice[1]=scalar(@value)-$slice[0] unless $slice[1]; | |||
855 | 32 | 100 | 73 | return $value->set([splice(@value,$slice[0],$slice[1])]) if $value->array; | |||
856 | 16 | 50 | 43 | return $value->set([map {$value->content->{$_}} splice(@value,$slice[0],$slice[1])]) if $value->hash; | |||
28 | 64 | ||||||
857 | } | ||||||
858 | |||||||
859 | sub slugify { | ||||||
860 | 12 | 12 | 1 | 15 | my $value=shift; | ||
861 | 12 | 33 | my $val=$value->repr(); | ||||
862 | 12 | 24 | $val=lc($val); | ||||
863 | 12 | 40 | $val=~s/[^\w\s]//g; | ||||
864 | 12 | 30 | $val=~s/^\s+//g; | ||||
865 | 12 | 31 | $val=~s/\s+$//g; | ||||
866 | 12 | 23 | $val=~s/\s/-/g; | ||||
867 | 12 | 36 | $value->safe(1); | ||||
868 | 12 | 32 | return $value->set($val); | ||||
869 | } | ||||||
870 | |||||||
871 | |||||||
872 | |||||||
873 | #This follows perls sprintf rules for now, which are about the same, but there is no "r" | ||||||
874 | |||||||
875 | sub stringformat { | ||||||
876 | 12 | 12 | 1 | 18 | my $value=shift; | ||
877 | 12 | 14 | my $format=shift; | ||||
878 | 12 | 50 | 26 | return $value unless $format; | |||
879 | 12 | 33 | $format=$format->repr; | ||||
880 | 12 | 19 | my $val=""; | ||||
881 | 12 | 100 | 29 | if ($format=~tr/r/s/) { | |||
882 | 4 | 14 | $val=$value->pyrepr; | ||||
883 | } | ||||||
884 | else { | ||||||
885 | 8 | 21 | $val=$value->repr; | ||||
886 | } | ||||||
887 | 12 | 26 | my $v; | ||||
888 | 12 | 12 | eval { | ||||
889 | 12 | 0 | 66 | local $SIG{__WARN__} = sub {}; | |||
0 | 0 | ||||||
890 | 12 | 66 | $v=sprintf("%$format",$val); | ||||
891 | }; | ||||||
892 | 12 | 50 | 46 | return $value->set($v) unless $@; | |||
893 | 0 | 0 | undef $@; | ||||
894 | 0 | 0 | return $value; | ||||
895 | } | ||||||
896 | |||||||
897 | sub striptags { | ||||||
898 | 12 | 12 | 1 | 15 | my $value=shift; | ||
899 | 12 | 31 | my $val=$value->repr; | ||||
900 | 12 | 20 | my $tags=shift; | ||||
901 | 12 | 92 | $val=~s/<[^>]+>//g; | ||||
902 | 12 | 35 | return $value->set($val); | ||||
903 | } | ||||||
904 | |||||||
905 | sub time { | ||||||
906 | 12 | 12 | 1 | 18 | my $value=shift; | ||
907 | 12 | 50 | 66 | 33 | return $value unless $value->number() or $value->array(); | ||
908 | 12 | 33 | my $time=$value->repr(); | ||||
909 | 12 | 25 | my $safe=0; | ||||
910 | 12 | 14 | my $string=shift; | ||||
911 | 12 | 50 | 33 | 47 | if (not defined $string or not $string->scalar()) { | ||
912 | 0 | 0 | $string=$Dotiac::DTL::DATE_FORMAT; | ||||
913 | 0 | 0 | $safe=1; | ||||
914 | } | ||||||
915 | else { | ||||||
916 | 12 | 34 | $safe=$string->safe(); | ||||
917 | 12 | 32 | $string=$string->repr; | ||||
918 | } | ||||||
919 | 12 | 20 | my @t; | ||||
920 | 12 | 100 | 28 | if ($value->number()) { | |||
921 | 8 | 22 | @t=localtime($time); | ||||
922 | } | ||||||
923 | else { | ||||||
924 | 4 | 6 | @t=@{$value->content}; | ||||
4 | 13 | ||||||
925 | } | ||||||
926 | 12 | 102 | my @s=split //,$string; | ||||
927 | 12 | 17 | my $res; | ||||
928 | 12 | 28 | while (my $s=shift(@s)) { | ||||
929 | 80 | 50 | 488 | if ($s eq '\\') { | |||
100 | |||||||
100 | |||||||
100 | |||||||
100 | |||||||
100 | |||||||
100 | |||||||
100 | |||||||
100 | |||||||
100 | |||||||
100 | |||||||
100 | |||||||
100 | |||||||
100 | |||||||
50 | |||||||
100 | |||||||
100 | |||||||
100 | |||||||
930 | 0 | 0 | $res.=shift(@s); | ||||
931 | } | ||||||
932 | elsif ($s eq "a") { | ||||||
933 | 4 | 50 | 0 | 14 | if ($t[2] > 12 or ($t[2] == 12 and $t[1] > 0)) { | ||
33 | |||||||
934 | 4 | 13 | $res.=$timeampm[0]; | ||||
935 | } | ||||||
936 | else { | ||||||
937 | 0 | 0 | $res.=$timeampm[1]; | ||||
938 | } | ||||||
939 | } | ||||||
940 | elsif ($s eq "A") { | ||||||
941 | 4 | 50 | 0 | 16 | if ($t[2] > 12 or ($t[2] == 12 and $t[1] > 0)) { | ||
33 | |||||||
942 | 4 | 13 | $res.=$timeampm[2]; | ||||
943 | } | ||||||
944 | else { | ||||||
945 | 0 | 0 | $res.=$timeampm[3]; | ||||
946 | } | ||||||
947 | } | ||||||
948 | elsif ($s eq "f") { | ||||||
949 | 4 | 8 | my $h=$t[2]; | ||||
950 | 4 | 6 | $h=$h%12; | ||||
951 | 4 | 50 | 7 | $h=12 unless $h; | |||
952 | 4 | 13 | $res.=$h; | ||||
953 | 4 | 50 | 23 | $res.=sprintf(":%02d",$t[1]) if ($t[1]); | |||
954 | } | ||||||
955 | elsif ($s eq "g") { | ||||||
956 | 4 | 7 | my $h=$t[2]; | ||||
957 | 4 | 6 | $h=$h%12; | ||||
958 | 4 | 50 | 9 | $h=12 unless $h; | |||
959 | 4 | 11 | $res.=$h; | ||||
960 | } | ||||||
961 | elsif ($s eq "G") { | ||||||
962 | 4 | 14 | $res.=$t[2]; | ||||
963 | } | ||||||
964 | elsif ($s eq "h") { | ||||||
965 | 4 | 8 | my $h=$t[2]; | ||||
966 | 4 | 5 | $h=$h%12; | ||||
967 | 4 | 50 | 15 | $h=12 unless $h; | |||
968 | 4 | 16 | $res.=sprintf("%02d",$h); | ||||
969 | } | ||||||
970 | elsif ($s eq "H") { | ||||||
971 | 8 | 33 | $res.=sprintf("%02d",$t[2]); | ||||
972 | } | ||||||
973 | elsif ($s eq "i") { | ||||||
974 | 8 | 27 | $res.=sprintf("%02d",$t[1]); | ||||
975 | } | ||||||
976 | elsif ($s eq "O") { | ||||||
977 | 4 | 12 | my @tt=localtime(0); | ||||
978 | 4 | 50 | 23 | $tt[2]+=1 if $t[8]; | |||
979 | 4 | 22 | $res.=sprintf("%+05d",$tt[2]*100+$tt[1]); | ||||
980 | } | ||||||
981 | elsif ($s eq "P") { | ||||||
982 | 8 | 50 | 33 | 37 | if ($t[2] == 12 and $t[1] == 0) { | ||
50 | 33 | ||||||
983 | 0 | 0 | $res.=$timespotnames[1]; | ||||
984 | } | ||||||
985 | elsif ($t[2] == 0 and $t[1] == 0) { | ||||||
986 | 0 | 0 | $res.=$timespotnames[0]; | ||||
987 | } | ||||||
988 | else { | ||||||
989 | 8 | 9 | my $h=$t[2]; | ||||
990 | 8 | 12 | $h=$h%12; | ||||
991 | 8 | 50 | 21 | $h=12 unless $h; | |||
992 | 8 | 11 | $res.=$h; | ||||
993 | 8 | 50 | 28 | $res.=sprintf(":%02d",$t[1]) if ($t[1]); | |||
994 | 8 | 50 | 0 | 21 | if ($t[2] > 12 or ($t[2] == 12 and $t[1] > 0)) { | ||
33 | |||||||
995 | 8 | 31 | $res.=" ".$timeampm[0]; | ||||
996 | } | ||||||
997 | else { | ||||||
998 | 0 | 0 | $res.=" ".$timeampm[1]; | ||||
999 | } | ||||||
1000 | } | ||||||
1001 | |||||||
1002 | } | ||||||
1003 | elsif ($s eq "s") { | ||||||
1004 | 4 | 14 | $res.=sprintf("%02d",$t[0]); | ||||
1005 | } | ||||||
1006 | elsif ($s eq "Z") { | ||||||
1007 | 4 | 13 | my @tt=localtime(0); | ||||
1008 | 4 | 50 | 23 | $tt[2]+=1 if $t[8]; | |||
1009 | 4 | 17 | $res.=$tt[2]*3600+$t[1]*60+$t[0]; | ||||
1010 | } | ||||||
1011 | elsif ($s eq "\n") { | ||||||
1012 | 4 | 10 | $res.="n"; | ||||
1013 | } | ||||||
1014 | elsif ($s eq "\t") { | ||||||
1015 | 0 | 0 | $res.="t"; | ||||
1016 | } | ||||||
1017 | elsif ($s eq "\f") { | ||||||
1018 | 4 | 13 | $res.="f"; | ||||
1019 | } | ||||||
1020 | elsif ($s eq "\b") { | ||||||
1021 | 4 | 11 | $res.="b"; | ||||
1022 | } | ||||||
1023 | elsif ($s eq "\r") { | ||||||
1024 | 4 | 12 | $res.="r"; | ||||
1025 | } | ||||||
1026 | else { | ||||||
1027 | 4 | 14 | $res.=$s; | ||||
1028 | } | ||||||
1029 | } | ||||||
1030 | 12 | 40 | return Dotiac::DTL::Value->new($res,$safe); | ||||
1031 | } | ||||||
1032 | |||||||
1033 | our @timenames=qw/year years month month week weeks day days hour hours minute minutes/; | ||||||
1034 | |||||||
1035 | sub timesince { | ||||||
1036 | 20 | 20 | 1 | 27 | my $val=shift; | ||
1037 | 20 | 50 | 53 | return $val unless $val->number; | |||
1038 | 20 | 54 | $val=$val->content; | ||||
1039 | 20 | 32 | my $comp=shift; | ||||
1040 | 20 | 50 | 33 | 71 | if ($comp and $comp->number) { | ||
1041 | 20 | 43 | $comp=$comp->content; | ||||
1042 | } | ||||||
1043 | else { | ||||||
1044 | 0 | 0 | $comp=CORE::time(); | ||||
1045 | } | ||||||
1046 | 20 | 40 | my $dist=$comp-$val; | ||||
1047 | 20 | 50 | 41 | return Dotiac::DTL::Value->safe("0 $timenames[11]") if $dist < 60; | |||
1048 | 20 | 30 | my $mi=int($dist/60); | ||||
1049 | 20 | 29 | my $h=int($mi/60); | ||||
1050 | 20 | 23 | $mi=$mi%60; | ||||
1051 | 20 | 25 | my $d=int($h/24); | ||||
1052 | 20 | 19 | $h=$h%24; | ||||
1053 | 20 | 27 | my $w=int($d/7); | ||||
1054 | 20 | 23 | my $m=int($d/30); | ||||
1055 | 20 | 50 | 29 | if ($m) { | |||
1056 | 0 | 0 | $d=$d%30; | ||||
1057 | } | ||||||
1058 | else { | ||||||
1059 | 20 | 22 | $d=$d%7; | ||||
1060 | } | ||||||
1061 | 20 | 24 | my $y=int($m/12); | ||||
1062 | 20 | 31 | $m=$m%12; | ||||
1063 | 20 | 100 | 36 | if (@_) { | |||
1064 | 8 | 0 | 89 | my $r=($y?"$y ".($y==1?"$timenames[0] ":"$timenames[1] "):"").($m?"$m ".($m==1?"$timenames[2] ":"$timenames[3] "):($w?"$w ".($w==1?"$timenames[4] ":"$timenames[5] "):"")).($d?"$d ".($d==1?"$timenames[6] ":"$timenames[7] "):"").($h?"$h ".($h==1?"$timenames[8] ":"$timenames[9] "):"").($mi?"$mi ".($mi==1?"$timenames[10] ":"$timenames[11] "):""); | |||
50 | |||||||
0 | |||||||
50 | |||||||
100 | |||||||
50 | |||||||
100 | |||||||
50 | |||||||
50 | |||||||
50 | |||||||
50 | |||||||
50 | |||||||
1065 | 8 | 25 | $r=~s/\s$//; | ||||
1066 | 8 | 29 | return Dotiac::DTL::Value->safe($r); | ||||
1067 | } | ||||||
1068 | 12 | 0 | 22 | return Dotiac::DTL::Value->safe("$y ".($y==1?$timenames[0]:$timenames[1])) if ($y); | |||
50 | |||||||
1069 | 12 | 0 | 26 | return Dotiac::DTL::Value->safe("$m ".($m==1?$timenames[2]:$timenames[3])) if ($m); | |||
50 | |||||||
1070 | 12 | 50 | 40 | return Dotiac::DTL::Value->safe("$w ".($w==1?$timenames[4]:$timenames[5])) if ($w); | |||
100 | |||||||
1071 | 8 | 0 | 16 | return Dotiac::DTL::Value->safe("$d ".($d==1?$timenames[6]:$timenames[7])) if ($d); | |||
50 | |||||||
1072 | 8 | 50 | 49 | return Dotiac::DTL::Value->safe("$h ".($h==1?$timenames[8]:$timenames[9]).($mi?" $mi ".($mi==1?$timenames[10]:$timenames[11]):"")) if $h; | |||
50 | |||||||
50 | |||||||
100 | |||||||
1073 | 4 | 50 | 30 | return Dotiac::DTL::Value->safe("$mi ".($mi==1?$timenames[10]:$timenames[11])) if ($mi); | |||
50 | |||||||
1074 | |||||||
1075 | } | ||||||
1076 | |||||||
1077 | sub timeuntil { | ||||||
1078 | 20 | 20 | 1 | 23 | my $val=shift; | ||
1079 | 20 | 50 | 51 | return $val unless $val->number; | |||
1080 | 20 | 49 | $val=$val->content; | ||||
1081 | 20 | 27 | my $comp=shift; | ||||
1082 | 20 | 50 | 33 | 67 | if ($comp and $comp->number) { | ||
1083 | 20 | 42 | $comp=$comp->content; | ||||
1084 | } | ||||||
1085 | else { | ||||||
1086 | 0 | 0 | $comp=CORE::time(); | ||||
1087 | } | ||||||
1088 | 20 | 33 | my $dist=$val-$comp; | ||||
1089 | 20 | 50 | 35 | return Dotiac::DTL::Value->safe("0 $timenames[11]") if $dist < 60; | |||
1090 | 20 | 28 | my $mi=int($dist/60); | ||||
1091 | 20 | 22 | my $h=int($mi/60); | ||||
1092 | 20 | 22 | $mi=$mi%60; | ||||
1093 | 20 | 22 | my $d=int($h/24); | ||||
1094 | 20 | 21 | $h=$h%24; | ||||
1095 | 20 | 21 | my $w=int($d/7); | ||||
1096 | 20 | 24 | my $m=int($d/30); | ||||
1097 | 20 | 50 | 29 | if ($m) { | |||
1098 | 0 | 0 | $d=$d%30; | ||||
1099 | } | ||||||
1100 | else { | ||||||
1101 | 20 | 21 | $d=$d%7; | ||||
1102 | } | ||||||
1103 | 20 | 25 | my $y=int($m/12); | ||||
1104 | 20 | 17 | $m=$m%12; | ||||
1105 | 20 | 100 | 33 | if (@_) { | |||
1106 | 8 | 0 | 110 | my $r=($y?"$y ".($y==1?"$timenames[0] ":"$timenames[1] "):"").($m?"$m ".($m==1?"$timenames[2] ":"$timenames[3] "):($w?"$w ".($w==1?"$timenames[4] ":"$timenames[5] "):"")).($d?"$d ".($d==1?"$timenames[6] ":"$timenames[7] "):"").($h?"$h ".($h==1?"$timenames[8] ":"$timenames[9] "):"").($mi?"$mi ".($mi==1?"$timenames[10] ":"$timenames[11] "):""); | |||
50 | |||||||
0 | |||||||
50 | |||||||
100 | |||||||
50 | |||||||
100 | |||||||
50 | |||||||
50 | |||||||
50 | |||||||
50 | |||||||
50 | |||||||
1107 | 8 | 24 | $r=~s/\s$//; | ||||
1108 | 8 | 26 | return Dotiac::DTL::Value->safe($r); | ||||
1109 | } | ||||||
1110 | 12 | 0 | 20 | return Dotiac::DTL::Value->safe("$y ".($y==1?$timenames[0]:$timenames[1])) if ($y); | |||
50 | |||||||
1111 | 12 | 0 | 20 | return Dotiac::DTL::Value->safe("$m ".($m==1?$timenames[2]:$timenames[3])) if ($m); | |||
50 | |||||||
1112 | 12 | 50 | 41 | return Dotiac::DTL::Value->safe("$w ".($w==1?$timenames[4]:$timenames[5])) if ($w); | |||
100 | |||||||
1113 | 8 | 0 | 14 | return Dotiac::DTL::Value->safe("$d ".($d==1?$timenames[6]:$timenames[7])) if ($d); | |||
50 | |||||||
1114 | 8 | 50 | 44 | return Dotiac::DTL::Value->safe("$h ".($h==1?$timenames[8]:$timenames[9]).($mi?" $mi ".($mi==1?$timenames[10]:$timenames[11]):"")) if $h; | |||
50 | |||||||
50 | |||||||
100 | |||||||
1115 | 4 | 50 | 30 | return Dotiac::DTL::Value->safe("$mi ".($mi==1?$timenames[10]:$timenames[11])) if ($mi); | |||
50 | |||||||
1116 | |||||||
1117 | } | ||||||
1118 | |||||||
1119 | sub title { | ||||||
1120 | 8 | 8 | 1 | 11 | my $val=shift; | ||
1121 | 8 | 21 | my $value=$val->repr(); | ||||
1122 | 8 | 42 | $value=~s/(\w+)/ucfirst($1)/eg; | ||||
12 | 35 | ||||||
1123 | 8 | 28 | return $val->set($value); | ||||
1124 | } | ||||||
1125 | |||||||
1126 | sub truncatewords { | ||||||
1127 | 8 | 8 | 1 | 11 | my $value=shift; | ||
1128 | 8 | 11 | my $words=shift; | ||||
1129 | 8 | 50 | 33 | 45 | return $value unless $words and $words->number; | ||
1130 | 8 | 23 | my @val = split /(\s+)/,$value->repr; | ||||
1131 | 8 | 29 | $words=($words->content-1)*2; | ||||
1132 | 8 | 100 | 31 | return $value if $words >= $#val; | |||
1133 | #$words=$#val if $words > $#val; | ||||||
1134 | 4 | 50 | 29 | return $value->set(CORE::join("",@val[0 .. $words],($val[$words]=~/\.\.\./?"":"..."))); | |||
1135 | } | ||||||
1136 | |||||||
1137 | my %singletags=qw/br 1 col 1 link 1 base 1 img 1 param 1 area 1 hr 1 input 1/; | ||||||
1138 | |||||||
1139 | sub truncatewords_html { | ||||||
1140 | 8 | 8 | 1 | 13 | my $val=shift; | ||
1141 | 8 | 23 | my $value=$val->string(); | ||||
1142 | 8 | 13 | my $words=shift; | ||||
1143 | 8 | 50 | 33 | 36 | return $val unless $words and $words->number; | ||
1144 | 8 | 13 | my $len=CORE::length($value); | ||||
1145 | 8 | 104 | $words=$words->content; | ||||
1146 | 8 | 15 | my $ret=""; | ||||
1147 | 8 | 11 | my @tags; | ||||
1148 | 8 | 100 | 67 | while ($words and (pos($value)||0) < $len) { | |||
100 | |||||||
1149 | 60 | 71 | my $pos=pos($value); | ||||
1150 | 60 | 100 | 1228 | if ($a=$value=~m/\G(\s*[^<\s]+\s*)/g) { | |||
1151 | 36 | 57 | $ret.=$1; | ||||
1152 | #warn "$1 $words"; | ||||||
1153 | 36 | 40 | $words--; | ||||
1154 | 36 | 159 | next; | ||||
1155 | } | ||||||
1156 | else { | ||||||
1157 | 24 | 59 | pos($value)=$pos; | ||||
1158 | } | ||||||
1159 | 24 | 50 | 99 | if ($a=$value=~m/\G\s* | |||
1160 | 24 | 50 | 77 | if ($a=$value=~m/([^>]+)>/g) { | |||
1161 | 24 | 53 | $ret.="<$1>"; | ||||
1162 | 24 | 39 | my $tag=lc($1); | ||||
1163 | 24 | 50 | 90 | if ($tag eq "/") { #SGML: Close last tag >, never seen it used in HTML, but whatever. | |||
100 | |||||||
50 | |||||||
1164 | 0 | 0 | shift @tags; | ||||
1165 | } | ||||||
1166 | elsif ($tag=~s/^\///) { | ||||||
1167 | 8 | 20 | my @t=@tags; | ||||
1168 | 8 | 311 | $tag=~m/^(\w+)/; | ||||
1169 | 8 | 16 | $tag=$1; | ||||
1170 | 8 | 13 | my $t=shift @t; | ||||
1171 | 8 | 66 | 69 | $t=shift @t while (@t and $t ne $tag); | |||
1172 | 8 | 50 | 17 | if ($t eq $tag) { | |||
1173 | 8 | 20 | @tags=@t; #SGML: bbb , the also closes . |
||||
1174 | } | ||||||
1175 | 8 | 47 | next; | ||||
1176 | } | ||||||
1177 | elsif ($tag=~s/\/$//) { #XML: Singletag | ||||||
1178 | 0 | 0 | next; | ||||
1179 | } | ||||||
1180 | else { | ||||||
1181 | 16 | 38 | $tag=~m/^(\w+)/; | ||||
1182 | 16 | 25 | $tag=$1; | ||||
1183 | 16 | 50 | 52 | unshift @tags,$tag unless $singletags{$tag}; #Some HTML-Tags shouldn't be closed, (why not, I wonder) | |||
1184 | 16 | 83 | next; | ||||
1185 | } | ||||||
1186 | } | ||||||
1187 | else { | ||||||
1188 | 0 | 0 | return $val->set($ret); #Parsingerror. | ||||
1189 | } | ||||||
1190 | } | ||||||
1191 | else { | ||||||
1192 | 0 | 0 | pos($value)=$pos; | ||||
1193 | } | ||||||
1194 | |||||||
1195 | } | ||||||
1196 | 8 | 100 | 27 | return $val if $words > 0; #Should be allright then. | |||
1197 | 4 | 20 | $ret=~s/\s+$//g; | ||||
1198 | 4 | 50 | 16 | $ret.="..." unless $ret=~m/\.\.\.$/; | |||
1199 | 4 | 6 | foreach my $t (@tags) { | ||||
1200 | 8 | 17 | $ret.="$t>"; | ||||
1201 | } | ||||||
1202 | 4 | 14 | return $val->set($ret); | ||||
1203 | } | ||||||
1204 | |||||||
1205 | |||||||
1206 | #TODO TODO TODO | ||||||
1207 | # Split in subfuntion ziehe safe aus $value->safe(); | ||||||
1208 | #TODO TODO TODO | ||||||
1209 | # | ||||||
1210 | my $unordered_list; | ||||||
1211 | $unordered_list = sub { | ||||||
1212 | my $e=shift; | ||||||
1213 | my $save=shift; | ||||||
1214 | my $level=shift; | ||||||
1215 | my $res=""; | ||||||
1216 | return "" unless ref $e and ref $e eq "ARRAY"; | ||||||
1217 | my @loop=@$e; | ||||||
1218 | while (@loop) { | ||||||
1219 | my $title=shift @loop; | ||||||
1220 | $title=$escape->($title) unless $save; | ||||||
1221 | $res.="\t"x($level)." |
||||||
1222 | if (ref $loop[0] and ref $loop[0] eq "ARRAY") { | ||||||
1223 | $res.="\n"."\t"x($level)."
|
||||||
1224 | $res.=$unordered_list->(shift(@loop),$save,$level+1); | ||||||
1225 | $res.="\t"x($level)."\n"; | ||||||
1226 | $res.="\t"x($level); | ||||||
1227 | } | ||||||
1228 | |||||||
1229 | $res.="\n" | ||||||
1230 | } | ||||||
1231 | return $res; | ||||||
1232 | |||||||
1233 | }; | ||||||
1234 | |||||||
1235 | sub unordered_list { | ||||||
1236 | 4 | 4 | 1 | 9 | my $value=shift; | ||
1237 | 4 | 50 | 14 | return " |
|||
1238 | 4 | 50 | 17 | return $value unless $value->array; | |||
1239 | 4 | 15 | my @loop=@$value; | ||||
1240 | 4 | 0 | 33 | 16 | if (@loop==2 and ref $loop[1] and Scalar::Util::reftype($loop[1]) eq "ARRAY" and (ref $loop[1]->[0] or not @{$loop[1]})) { | ||
33 | |||||||
0 | |||||||
0 | |||||||
1241 | #$ret.=unordered_list($loop[0],$save,$level); | ||||||
1242 | my $r=sub { | ||||||
1243 | 0 | 0 | 0 | my $d=shift; | |||
1244 | 0 | 0 | my $r=shift; | ||||
1245 | 0 | 0 | return ($d->[0],[map {$r->($_,$r)} @{$d->[1]}]); | ||||
0 | 0 | ||||||
0 | 0 | ||||||
1246 | 0 | 0 | }; | ||||
1247 | 0 | 0 | @loop=$r->($value,$r); | ||||
1248 | #@loop=($loop[0],[map {@$_} @{$loop[1]}]); | ||||||
1249 | } | ||||||
1250 | 4 | 13 | my $ret=$unordered_list->($value->content(),$value->safe,0); | ||||
1251 | 4 | 20 | return Dotiac::DTL::Value->safe($ret); | ||||
1252 | } | ||||||
1253 | |||||||
1254 | |||||||
1255 | sub upper { | ||||||
1256 | 36 | 36 | 1 | 74 | my $value=shift; | ||
1257 | 36 | 122 | $value->set(uc $value->repr); | ||||
1258 | 36 | 122 | return $value; | ||||
1259 | } | ||||||
1260 | |||||||
1261 | #This awesome Regex ripped of http://geekswithblogs.net/casualjim/archive/2005/12/01/61722.aspx | ||||||
1262 | |||||||
1263 | #Addition: parameters: Safechars. urlencode:"" encodes also slashes, needed if you are gonna built an url and urlencode:":/?=&" can be run over an http://foo/bar?foo=bar string | ||||||
1264 | sub urlencode { | ||||||
1265 | 104 | 104 | 1 | 152 | my $val=shift; | ||
1266 | 104 | 287 | my $value=$val->repr; | ||||
1267 | 104 | 212 | my $safe="/"; | ||||
1268 | 104 | 100 | 262 | if (@_) { | |||
1269 | 100 | 129 | $safe=shift; | ||||
1270 | 100 | 100 | 259 | $safe=$safe->repr() if ref $safe; # For internal use | |||
1271 | } | ||||||
1272 | 104 | 100 | 218 | $safe="" unless $safe; | |||
1273 | 104 | 156 | $safe=quotemeta($safe); | ||||
1274 | 104 | 2039 | my $find=qr/([^\w$safe\.~-])/; | ||||
1275 | 104 | 440 | $value=~s/$find/uc sprintf("%%%02x",ord($1))/eg; | ||||
20 | 98 | ||||||
1276 | 104 | 339 | return $val->set($value); | ||||
1277 | } | ||||||
1278 | |||||||
1279 | sub urlize { | ||||||
1280 | 8 | 8 | 1 | 12 | my $value=shift; | ||
1281 | 8 | 26 | $value=$value->string(); | ||||
1282 | #$value=~s"(^|(?'.$a.''"eg; | ||||||
1283 | 8 | 50 | 101 | $value=~s"((?#Protocol)(?:(?:ht|f)tp(?:s?)\:\/\/|~/|/)?(?#Username:Password)(?:\w+:\w+@)?(?#Subdomains)(?:(?:[-\w]+\.)+(?#TopLevel Domains)(?:com|org|net|gov|mil|biz|info|mobi|name|aero|jobs|museum|travel|[a-z]{2}))(?#Port)(?::[\d]{1,5})?(?#Directories)(?:(?:(?:/(?:[-\w~!\$+|.,=]|%[a-f\d]{2})+)+|/)+|\?|#)?(?#Query)(?:(?:\?(?:[-\w~!\$+|.,*:]|%[a-f\d{2}])+=(?:[-\w~!\$+|.,*:=]|%[a-f\d]{2})*)(?:(?:&|&|;)(?:[-\w~!\$+|.,*:]|%[a-f\d{2}])+=(?:[-\w~!\$+|.,*:=]|%[a-f\d]{2})*)*)*(?#Anchor)(?:#(?:[-\w~!\$+|.,*:=]|%[a-f\d]{2})*)?)"my $a=$1;''.$a.''"eg; | |||
8 | 17 | ||||||
8 | 50 | ||||||
1284 | 8 | 28 | return Dotiac::DTL::Value->safe($value); | ||||
1285 | } | ||||||
1286 | |||||||
1287 | sub urlizetrunc { | ||||||
1288 | 8 | 8 | 1 | 17 | my $value=shift; | ||
1289 | 8 | 29 | $value=$value->string(); | ||||
1290 | 8 | 17 | my $len=shift; | ||||
1291 | 8 | 50 | 33 | 37 | if ($len and $len->number) { | ||
1292 | 8 | 28 | $len=int($len->content); | ||||
1293 | } | ||||||
1294 | else { | ||||||
1295 | 0 | 0 | $len=0; | ||||
1296 | } | ||||||
1297 | 8 | 50 | 23 | $len=15 unless $len; | |||
1298 | #$value=~s"(^|(?'.($len >= CORE::length($a)?$a:substr($a,0,$len).'...').''"eg; | ||||||
1299 | 8 | 50 | 110 | $value=~s"((?#Protocol)(?:(?:ht|f)tp(?:s?)\:\/\/|~/|/)?(?#Username:Password)(?:\w+:\w+@)?(?#Subdomains)(?:(?:[-\w]+\.)+(?#TopLevel Domains)(?:com|org|net|gov|mil|biz|info|mobi|name|aero|jobs|museum|travel|[a-z]{2}))(?#Port)(?::[\d]{1,5})?(?#Directories)(?:(?:(?:/(?:[-\w~!\$+|.,=]|%[a-f\d]{2})+)+|/)+|\?|#)?(?#Query)(?:(?:\?(?:[-\w~!\$+|.,*:]|%[a-f\d{2}])+=(?:[-\w~!\$+|.,*:=]|%[a-f\d]{2})*)(?:(?:&|&|;)(?:[-\w~!\$+|.,*:]|%[a-f\d{2}])+=(?:[-\w~!\$+|.,*:=]|%[a-f\d]{2})*)*)*(?#Anchor)(?:#(?:[-\w~!\$+|.,*:=]|%[a-f\d]{2})*)?)"my $a=$1;''.($len >= CORE::length($a)?$a:substr($a,0,$len).'...').''"eg; | |||
8 | 50 | 18 | |||||
8 | 73 | ||||||
1300 | 8 | 33 | return Dotiac::DTL::Value->safe($value); | ||||
1301 | } | ||||||
1302 | |||||||
1303 | |||||||
1304 | |||||||
1305 | sub wordcount { | ||||||
1306 | 12 | 12 | 1 | 17 | my $value=shift; | ||
1307 | 12 | 32 | $value=$value->repr; | ||||
1308 | 12 | 106 | return Dotiac::DTL::Value->safe(scalar( ()=$value=~m/\S+/g)); | ||||
1309 | } | ||||||
1310 | |||||||
1311 | sub wordwrap { | ||||||
1312 | 4 | 4 | 1 | 6 | my $val=shift; | ||
1313 | 4 | 15 | my @value = split /(\s+)/,$val->repr; | ||||
1314 | 4 | 12 | my $len=shift; | ||||
1315 | 4 | 50 | 33 | 17 | if ($len and $len->number) { | ||
1316 | 4 | 13 | $len=int($len->content); | ||||
1317 | } | ||||||
1318 | else { | ||||||
1319 | 0 | 0 | $len=0; | ||||
1320 | } | ||||||
1321 | 4 | 50 | 12 | $len=80 unless $len; | |||
1322 | 4 | 7 | my $line=shift @value; | ||||
1323 | 4 | 5 | my $ret=""; | ||||
1324 | 4 | 10 | while (my $space=shift(@value)) { | ||||
1325 | 20 | 23 | my $word=shift(@value); | ||||
1326 | 20 | 50 | 42 | $word="" unless $word; | |||
1327 | 20 | 100 | 41 | if (CORE::length($line.$space.$word) > $len) { | |||
1328 | 16 | 20 | $ret.=$line."\n"; | ||||
1329 | 16 | 41 | $line=$word; | ||||
1330 | } | ||||||
1331 | else { | ||||||
1332 | 4 | 13 | $line.=$space.$word; | ||||
1333 | } | ||||||
1334 | } | ||||||
1335 | 4 | 6 | $ret.=$line; | ||||
1336 | 4 | 11 | return $val->set($ret); | ||||
1337 | } | ||||||
1338 | |||||||
1339 | |||||||
1340 | |||||||
1341 | sub yesno { | ||||||
1342 | 48 | 48 | 1 | 56 | my $value=shift; | ||
1343 | 48 | 54 | my $yes=shift; | ||||
1344 | 48 | 100 | 87 | if (@_) { | |||
1345 | 24 | 28 | my $no=shift; | ||||
1346 | 24 | 24 | my $undef=shift; | ||||
1347 | 24 | 50 | 45 | $yes=Dotiac::DTL::Value->safe("") unless $yes; | |||
1348 | 24 | 50 | 41 | $no=Dotiac::DTL::Value->safe("") unless $no; | |||
1349 | 24 | 100 | 41 | $undef=$no unless $undef; | |||
1350 | 24 | 100 | 54 | return $yes if $value->true; | |||
1351 | 16 | 100 | 41 | return $undef if $value->undef; | |||
1352 | 8 | 22 | return $no; | ||||
1353 | } | ||||||
1354 | 24 | 50 | 42 | if ($yes) { | |||
1355 | 24 | 61 | $yes=$yes->string(); | ||||
1356 | } | ||||||
1357 | else { | ||||||
1358 | 0 | 0 | $yes=""; | ||||
1359 | } | ||||||
1360 | 24 | 66 | my ($y,$no,$undef) = split /,/,$yes,3; | ||||
1361 | 24 | 50 | 51 | $no="" unless $no; | |||
1362 | 24 | 100 | 36 | $undef=$no unless $undef; | |||
1363 | 24 | 100 | 66 | return Dotiac::DTL::Value->safe($y) if $value->true; | |||
1364 | 16 | 100 | 38 | return Dotiac::DTL::Value->safe($undef) if $value->undef; | |||
1365 | 8 | 25 | return Dotiac::DTL::Value->safe($no); | ||||
1366 | } | ||||||
1367 | |||||||
1368 | |||||||
1369 | =head1 SEE ALSO | ||||||
1370 | |||||||
1371 | L |
||||||
1372 | |||||||
1373 | =cut | ||||||
1374 | 1; | ||||||
1375 | |||||||
1376 | __END__ |