| 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__ |