XML-Hash-LX-0.0603/000755 002100 002100 00000000000 11623443777 013430 5ustar00monsmons000000 000000 XML-Hash-LX-0.0603/inc/000755 002100 002100 00000000000 11623443777 014201 5ustar00monsmons000000 000000 XML-Hash-LX-0.0603/Changes000644 002100 002100 00000001445 11623443753 014721 0ustar00monsmons000000 000000 Revision history for XML-Hash-LX TODO: make hash2xml faster 0.0603 2011-08-19 - Fix tests 0.0602 2011-08-18 - Merge encoding patch from ~gugu 0.06_01 2011-06-16 - Fix when attribute/cdata/comment value is empty/undef - Cleanup tests (move qualitee tests to xt/*) - add bt/* - benchmark testing draft 0.06 2009-09-15 Fix dist: remove cpants.pl from install 0.05 2009-09-03 Fix: work with earlier versions of XML::LibXML (for ex 1.58) Remove Catalyst stuff from distribution, make it separate 0.04 2009-08-27 Fight for kwalitee. No major changes in code 0.03 2009-08-26 Fix deps on Catalyst::Action 0.02 2009-08-26 Optimize work with text in hash2xml 0.01 2009-08-12 First version XML-Hash-LX-0.0603/ex/000755 002100 002100 00000000000 11623443777 014044 5ustar00monsmons000000 000000 XML-Hash-LX-0.0603/MANIFEST000644 002100 002100 00000001146 11623443762 014555 0ustar00monsmons000000 000000 .gitignore Changes ex/benchmark.pl ex/profile.pl ex/test.pl ex/xml.pl ex/xpath.pl inc/Module/AutoInstall.pm inc/Module/Install.pm inc/Module/Install/AutoInstall.pm inc/Module/Install/Base.pm inc/Module/Install/Can.pm inc/Module/Install/Fetch.pm inc/Module/Install/Include.pm inc/Module/Install/Makefile.pm inc/Module/Install/Metadata.pm inc/Module/Install/Win32.pm inc/Module/Install/WriteAll.pm lib/XML/Hash/LX.pm LICENSE Makefile.PL MANIFEST This list of files MANIFEST.SKIP META.yml README t/00-load.t t/01-conv.t t/02-inject.t t/03-no-inject.t t/pod-coverage.t t/pod.t XML-Hash-LX-0.0602.tar.gz xt/99-dist.t XML-Hash-LX-0.0603/t/000755 002100 002100 00000000000 11623443777 013673 5ustar00monsmons000000 000000 XML-Hash-LX-0.0603/META.yml000644 002100 002100 00000001304 11623443762 014671 0ustar00monsmons000000 000000 --- abstract: 'Convert hash to xml and xml to hash using LibXML' author: - 'Mons Anderson, C<< >>' - 'Mons Anderson ' build_requires: ExtUtils::MakeMaker: 6.42 Test::More: 0 lib::abs: 0.90 configure_requires: ExtUtils::MakeMaker: 6.42 distribution_type: module generated_by: 'Module::Install version 1.01' license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: 1.4 name: XML-Hash-LX no_index: directory: - inc - t - xt provides: XML::Hash::LX: file: lib/XML/Hash/LX.pm version: 0.0603 requires: XML::LibXML: 0 perl: 5.6.2 resources: license: http://dev.perl.org/licenses/ version: 0.0603 XML-Hash-LX-0.0603/XML-Hash-LX-0.0602.tar.gz000644 002100 002100 00000316034 11623170332 017133 0ustar00monsmons000000 000000 LNXML-Hash-LX-0.0602.tarT˲'{m,w w6 X %;3̷fyfk_Uk+)2˚8Y1+j3qBg666^nnK`cbpCg'(v`{ټ_GH7cl.vn%L-Ng9xy۟ //j@l9A #o彊zpX8A((Wa(-do p0Y,vKgK?af4 j@ SgbjC.&@ s:ۛ-F/a 4wv@N'lb uB7+ߨL/}/MɭLm{&?=6QNJf&'?79m;6ο_uA@G[tm''}A/5nvn߉ڟK( p8[X)oP 7? zt0q4EchV?N럚d(_xXt6^x8F</bfe8@@v A~/ozӳsmamKC g_2gws?7'X K{#寸^#d 7|zw*  y,vXMdHH_"2&goflx* ߱?sr1s S֗>*jRRVB(v?߿Dm@w(*{1PTTB1ۂMY f`{? {k/Nf{;/s_o/>X^Kd;x/C_7x/_$ps + 333KFhbJG2G~؛Q|;3E1qXP~gϴJTLwr)!$$Th)9?Ѣ:l͍A@KHA4 ['߀(a!^" l勅 ,@Ύ &A^(@{T]&~ \$l/nwz!v:ڢؽ N@k;; V?Y3c'%~Z{  ; B\(&v/klzѬ_kuGg@ 乀/ Y (jI;1AZe~B{⟻c?V́.,'> : S?6^^^|\< )TQ?6;aB5j@3w c ;2"wCs}gђ7)]㽤=]z&N}ʊՕ<<<ԉ ]=N(!u"ˍe\ ˩K[#h_Uz 2)--ʶct"qTmŵ"Dbsvue?w@LKlJJ#YN˻"ECmwYAW=,!{Ffpvnn#d89R<[hXJZ>.A%Z@yy%*=}nHmzn<\Y<.̈=3@eZp8C\>,v].Zllvpypz>s"n"LB.,.܍t?4Ths-jksFjP֨y.QP>tQty󡉰Ϸ$:h:Iyo&)U"|Nvs}]( W3{F}~9 yL̹F*֋ ?6=?? .]h-\x[q]J>O>n] TjR%|#}P<G?5y^ ~ xqSz"}ſo?}nzᨒ[cYKIe{ˌbeDgD}'|ߔO+=ȶ;usWJgmN0p4I:#%{~+yt9щ=QʹB"qԖuyڡϮW;F:oGR@-\3&:o? |dW"/L$s Z|pf\yCv?ߔggJej']s"NעF`לdJÙșh{qzO3@VBwleYfq ۠ݠԸ Y^c v^I b&urŊr̕w߾o{{(TnunȾfbب>J AB"o"by ~;T B:ّN0gk2XvL髱XqȒ g$_RKq檵m=c9iM:%D-Z(úȈATx^iH.zztE ,h2L7|([1_ %].fabOU1}~Z@aXNz]Rc&Mim@r{Xgz[_;5TofrϹ6:nnut=[*hsQ abݖ٦ϊg޹ ɯQ oO l:ߨ8% zI@_L M7PP)%8`r^{ؑǯ?ӃǚG|1b0 Hs(H }g'Vɧ 8!1]pDAZ6<<TM^v+f{+w۩.vVʙGo^6!'2vWm/On4Y$^^%}/ZPpUB'$Ä+Xafa!Iy TN5[>T`Pi._ 8Wtr JBRPw4yط/}׽$ӋxN&P#O2[NRu-֠kNHobc#E%Ge G_5&ƑRh7c^y]}@i獜ю>:I1t|Gڨh/5bQ~nyuHFq_81M?+99<2x^`\ ۼ[CяB7sM`>c"%kk$Ť?5}хvw'<҈hߺNS9ʮЃ \o'D׹fçJm7-Qpԟ {{QcGdڬYK & Yluz& 8Drc?\_?I/,TSZb*_ )XhnU 20"sI|U`Cˀ [i+u~6< fxpBGDi)MPF 30m 6t<ļ&ࠨ88Jm?&W* zgQѹØĄ fQ:/|SH+ &=2$Shne]8D=K0d= Cb  ~Z`s8 (e9{SՊ%%s|-*gZjXk0?Չzׇ_ 35V4RX PjZ~A}?a`GHmG7}J; ǰ9?XnUE;{ÏdNd iP( و/lGh)) ş& Ǩ$A'~-̢h 6gv a I3qAFq;<7:<.J3c2OLoI5 ҈-j7dq]?V@'afAO(֯J~E0_y')MDq4f&xw3n ye+%R!چm&}VlF! i^nа5E'E+vREMoc7z'r:ƮjF$I rRJHCI/쁂״<^%:p#jDX vjTƁ4T@(1&FU c_tx;Q,e01 8 5WZXԫhD7Sbޕ?wJQQlx;%}:t|5uZz?!i#9Cud p&Ϗ+VvloVI:m;!3ژh0rC?\vT)q[MT;0? y.o`Ƥbo+:V :dTxWq o)kɱD?ĝ|Ƚw1KVɣ5gDܱAilQt:YsiEH Jl9?n+,&8Y<FdqJ ~bdPxX;%e_KC0m(2?8v,qM5A>X #WޟScNG݄_Y$l8FWPm\|x!eE*ȡܦQgLB`l>>wd6EWzWvF.Xa=_aFMyv:ɦ%}`-5V*'v])JELrybZ"mor^z-`tPKԿ}<Kd*B͎-fRZ;†L*ʨL ԷɤAņtuIɄo}m ::\;3-h=+ѴF\o<#>AžNS7#MiM)u)7co}N_:\<%:rŮI( &Ceֹl4?jK"WlQXW&-kpl0=M+)ieGH)Qihz5}lֻB`J,)a=>юS]E$n;S  ||$`ڒP k" g'V$U"0 [gl@gauV1y} Jf>NZ˓dmҧ ŧ1Q]&v~U%autU-]%Wd;23Ɂn$J3Qqӽ,-@ZkR[@EB(E&9ο}"\$"NK}Lz/g}P*ʸ DKм)>c !Vu-lccdjf*`{좰@qlV*-ӍMf.2m)RGᡓ" L'z,aۡSy"F+_Gk œ"_v>/L쐰i-[q5/Î n7gƠm:tD$|0sg2[5~}E@d{~nʎCGq={DeXą>YWSy1˯=]E -pt`M#Cuu!}1PPą׸ᙙqv|Yhq b7L҅] «d)F*H7<wEd5g?gZ#?d{ da*zưq)t|pޘa*|\U( 3["}3!C*[V:԰̟9q(=Z9PjZ^vKP!k]e4gH_i+urGqwP2 <:\Т|BΞ,+OhZ5W!(mun}PH㶗7ۄ ˝pN#nPC-l~ Lc\Ep\V~nޥbm܎m8ih5]y+3{9 j  rAC!#ǜyA%Yjs/uw f0xPIƅOt!\3@G;;i@Wvx+r)^U2/6Im emp'?ŮEړ376bLrH9fĤu5tS%o^[2uSJp"wJ{WؽvRd{uJ(E3Â`6nGoxGVH]n!cv#jnlFfZKc,c{ak\ϷLMq6*kĺ0=(ool~KTeW8ikX}m)m3Z Z@[Yħ3=Pw~4w8 T璫A.=. gJ~!$@f 3ol}6&_<Wh!W]B>;Χ5ĉ3%Qք3@nGl3Et}QRawL1ZfkUqRpAj A. WVI 0Cef/1“=}J>K0NjO4O h>|r/֐Ȟfemqdm𧒉/ ^| 9"}b 33L1̪2jMs xq[gzW&bBp}`xvP g!3"~:dZddIfO檸"^OR4fx.8qAD5ӗ9_e}޼R𙦓V~ʣҳAoN0⌫ ="!y4Jv9לiQά,z"e@%~+iu 4CШұwpD]V🦓#7=E$d(!fZ GwmsmpǠ/ql'-o; ?x[pC)q*-oV|xDw`2s}ei ʖڧ")N ߻B\m`^'ߛaN1l5̷ϧ\#E<[5^ۉWll@V͘| Z- ):|j;d =U_l>օٹ.v oREyzܢ:Iͨ΅.]x;o3#$BP E<ɪiY(nf7Dʣ/p]ǬH`-ۺPв6U QdXbzp$RIUqZҢ LpH36DY:l䰞o/^'A{T8v OxS':s_jTN7۹H]' ODS.Z9nڱ Vz> "MloBLxO -a3/`{Bٞa<c Ś@qÔZƍNID.$Ɇ;:;ޜYEz#j~70qXe^ Pn-oKd~|`;7ڛ`WAٳBz*)xOa=fע;W}._13ÞCf?gOdZJ8NuV3CK !ކO{?Y V-4=鋝IXRB1 ֦z 8O9oIy҄Ɓ96yb2,iAVgR2J ^MOlL"IFNQ3}RmOJI Z"Ax}ԙoV Fr&"E#T‡S" HKS!3{G݆C 7Nq÷VܖLjHvkFr*zyۥb60: %r1+Kpamqd%tR+NUJqnT"HOSKe"&N#aȀFA$UAr:y92[ h6|bOxU} X_㷳!}bb+?LrnjƿCOk;Β*4{_Yz]ɱ@cj)ts/s[È."$W"T{k{aү0CYA?Q5EϜ%>Vn 79)`=ƹ-OCE_ȵL`y=,e)vuI4t0q=` m;!'#ם!~MT );p=M*bU1e! ZF|s,53a 1}|*ͧz=7ql>0}}>\`XSAlcܻ`2}+}[*:.hYפVF*)8I{?W !b԰KIDhP$\O$ 8uʒb=knN=2QtFx1_5vn\&@ݵR-GHH:ukS<MfG/5^x!3̠ըhKLuGʳؑ622zmъڰ K N>G s}t}ש8(0fL.ZۈTQ|sXrUk V+IV ycB>wIxY>SJOm#)ױ5&ySڏobӱn44ܧe`nƪxp |~QY9X|B9H`$,[ۍc<~aem(J_=$Cb=k} ъcBx[G$-R**[AJUه>_[RsU#JƗnib m*;H͈~5=^ft|B\icܞ)Z:qdF7Fm2>ׯHic|'oՐe U3%^7qքgl'й&ƑXѣQ J09uZZ%F5ߙVHՍg7OR_R:q WúVuٟ$L9T'&yǔEnKwPF5?<3}SSmA'K−PBsF&#D/qpmG4gDF{spoȼ? rBڜK gvY)6;zXT0?r>S)> m/Bgǧw}i!cF#_ry#vMEg |bH&}Z$aSr7h7W{F8O@N9dh.![r&xkwuu&(T觝Wvf삭~$B+!$P>J.5uG'H)B7.D<ц>F.rHj][֒ÅUҜ#ɐU'FO :lU߲ aepLSwH7|#PRw=d=(|xxAn*1BIyI_iN0钐蜬Tꕂj`9  ڲ6L[{R`vm;xh>TKi,e(Z=T0nz9.8[R ;7k_2,-cZvԘԝ:n&xvTf8dm|ʰ)쾒t='r8ּj!?8phnuux>Gw˻o<@-hqBFf@}.6RcQѴ댹xeI`ɿ߽!me5=f]1 O,@JF~-LkNnn*갿6~nEp=JN)@P67'8!2r +vںja9ϺUgkc%FA+Pl 4ogUY4BjQQyy7Dxh-xSQN x~ѥiF<]^M#B[`kt* bzL'`4~J#~VA\Ժo7d{\UL!I-9(ȜĈlԇgL'{_d^D~ͩ?5 7 )4oڪ~ G^xnYlH.X0y zk0X fxZ["rS+RZ!yhT@;5Qy` axnEl/ 5O/ n-(mMRUwG0Q|cT' uph1‰MM ʌ=Yi P􄯑?GBRv2hZquQLv--1F4^E%6F0V h6۽~ gE"b&~#Fධ#lc>8[yQGpxxRfB _-be.].'ص*CWQo%5gSzȥޑdjn\+nş$Pv3! 9zY$sPkntB,I#Ej[To ;璭`f4SC d-;\8+_9lٱ%lj|^pddZp@ 媀L2E 0G3/Cmɰr{f\lD. Bt%RW=ݭ\U{O# 5W'Jp:pPrhzز xMI6I}nAE9Rq@va}n۱Z~EJOGլN]kC#ݽ֣N47mcnmZ{;tslRB$eOo,OVotyމraBSj$Tfюb҈xF;ɪoz!FUOa h p֞]ӻe$n5T49[h-dE~҉z}Ͷ%uºঅX !Hc޶Z"_3{}ŐYAITh ྶ8{b8Q1j@:"zqf]xMЎ^6~eH)6mE?b-ݠmF3Ez"#fC\B`ThR0&3G5ītK(Kl7k]AX9AvJSmdm:AVd73qV5=5r9&>&1dnF^ťW`(7J"sFQH˘]7MC }"F\MQ<9~,E3<8h(l6o*;z灞\,1mhF3FZ"eW1 78Bq io7eӪ` ѫ4 ق_-vQcHʹgDs&X s6S1?hJSl5"PVGE%kT1‹=Z$i)R|r`hj^0b/7Bf9JT!'᭟$4ɒ͂$jd=94za'~a =Ž /%plHr  ld9%DMYҗ,0V(˒`Rn# [ެG:Ofgϣ%߇ y$JXC.>/}!dA[Ymi|m֐XZq)]'hͲ$K5ЉŤ̒<k'ıˈXYS:o(ceWɀvP6<)e0_gɺPw1JME/CKA8ZVwzM}6ʾ>60Iyޤwt4R$$l0[k dz.t3El VrLQ`yKnBqM_0q;[JSZX;%qNḊeM"b:ىPn n_$o=; zRǹ$WNl̻Nf?ЬD5e$0V|&V(RsZ~}zi(,Hx$Rf\M ]VQ;F#ӏ3?U:mpqlql%&a=s!C7x-7@e >'ܾY#"^M&OᎣi0#T`7ddAƹ ; ^(% u㵿"~@>MJ8s!j 3+~\7̣(A)c3Ƚ=K Ed/GrZ\2g9ǡ$:88-{VS򍌪MQWbKR+ըt{@Y/$rE!heL8 |DKJ>r̔96qhTG Uc ئd.z{Bbت1ys 5X `NzK?9⼃]َv9ُY|pv~s7[eKwQKwcrL\dB})r߻8Y\IQY$|| 1K#KW1qm~Ǐ=j B ګ@4AqgU :_se#=MA%aV6H}]}VwCvS~&.*@]lx %ޱK P3퉶: DMɄĶUοW T@%l?Ct2prI%x&]x=1 eو3.aSZ߼ Z <ւve4 90I䣚2z}}8֋kC<á1oͣLPwr0 X%6 *jc#}o*@OgSea?FJ)W7PBz+qA)ܠ0@sL :F +]`ep&E\-LEM7)q-а¯LȖ0ߦE{H>&kخɁk~!qs79K~8Q'-~L ?3[&d$0"ŧHd'v,&4!xXx!@S]$9/$4%BzeNmj!V֤=n`jԕ4Zv6ֹLd >}o49\nh@s~weϗikaBW?J^,{agkػ6?e:ˌCl~Nk x9\J-O#!VCiSG|/WL7ͧ#yewRSho(.xt=Y&i,GގOՉ"B2"!tk8]I}-5xӂTk߁p[\aS7cGcPZ6#GqZ6 \;uֵQS8뉽\ cd^z$٫L#*aNy(E^ؘi u_^9^{9L_muO"kA?`T눫/}\AIh?]Y˷ܧƂ9 <|⬸YQ״an(yT jx3/ڴ{ 6+}?uyFe[Βkf!HA!.f]21s>rQ r[l z#_"ӕPjRDZ¬q:l`YXCU8"C<'ֿ>q}&BD=h:7A&ͳ+3C'Z/vtٱuʅ-uc>jL+ 3xZABٱ.ޮ ңY&>)ݚĂ$[ȥFiBljޫ/(/}ֱ`o9",͝Y S*[5A)Z?XB;-# @iTq578$Җ3D9/+{;z5KkθAv[9EN- ǮKB .D#'#mmyзn֞LQ tJ=}01{" ?Q!(ȞL4DMǠ.aZ }0.)B"dǞ tѧBcIX?ب꫖o]RʬRsØq8l͜6s:Br=!%SNNQU *APPT,A.&f0tq-oh$pJ*>Y'h&C!:-Px򐅛搥qsv_oY:ɇx1 @cvOGEkyh.Ԑ^Q0A"G9TRo~ZFrkcY{ a(# Mb*Ū|N?q\8X>q10`y=$2.^AՋ&Q_9 |YU%E=ύ[JPJji 0}1Ga8w$ {_"7T^0%DՎXs/s俇S5msqH b克/2`'?1tb]$a;C#|9_boTkt1Ǘ`АWkLbT*MWP9K@USBaEƗ%دo,7W?J W$ԧ:IZz U|v6ץ`&w.Ufky_tΉö '*?= Zo lIqE{ v[ Ypr~V.CO6XQ2^}D" Zp ,4UtfP  2]ζlDK&P0 $^"mmovgã-y8gd[hF( XCk)iIcJR*S3Kwܖ4 u ѧ5WȻ׀ُ;7v B8qֻwpRo[ԝ⤤Eoȃ W%F2ȁ@!ya{",E Bqp2_-Eqsa` `ghcwwL*YeǣDҰ[^ڒ{lQ. ʋbJ')UYBX%rP ʍ/mid!ŸP: W@\܍j*QlF PuMm ]u>+pr ZSET\UM*x8Sd6 䘷 ?GZ`};r0(&}v_()ѐUd` ܚEEB*q ,%cl+Hl ړN$7זԇ}'2SQm"|'ꈩŔBH|99-NxBSOMNwۨI cAǰ3hwtJafI;1JCAI(&2L"/OY'A&=خ:U3 ;|m =VC*>i.{u+oih:  y{tvK jɍ,PHgGL!Jֱ=b-PF;Y0j;J~7H~\7TDwʐ t9g˷ʄ CUXNC_8:Fd}1p+TK,M}h\$К &ѦH vE;N7/,b& { X^Gp!U(g= &ZQDAXV.,? ŭ.E9KсsKŸߐ!TD ;pbinAt(ji%Z3Ou-SzZb0d+^gytA]qkK`>=>px׉N.֥1plHVOI?#ŇG[X9&$Fȹ`@,|y8XI} K5^?2+QNk)nƗ8[t!OGWGv`ez؝&u6 Sv5e;vl;P4 1&_2\L `b$>qJ)uJ1~8ZH޿\Y4z.[E4 xf䃋N/$o1تDxΈ.'ۮd0+€::R,H[{̯r\,bcnBT\5yO]EzĿ$پhTHaX [&W3ۢ, ?;4Q+#< Ga[8`+"uc@mn~;CA5(5[;ug='HB8m]ڨk]ލGc?fhf]TΑ|* bFvwCeWW=Se2 cC1.LZoSSڳ8\hQzhZS|5YjaZ;x ,ԅ&!bc UlG lvÀkx/V1vj{ƽ)5H3,5 Q$tQl!E13'^tnCw PFZW5yo9yNGfA1ڎy\:F|)Cc]>Oubg> 2˦^/ ZHbo=J'$ҙĖn n߁M`bkŇQfNrPdWz) GoSkTCQ(SQ~Ё#YeK#=%O[. RF_*<ϷPZ +CMk(>U{[cE^"J/JTl7 Je:MG$.|64(c NjPU8AS!Ӑ0|fVMB΄z0b(쎧"q#~lb=[&`EDݺr [: lԾ ߟٰ:Mjf#20X㓱:3Ae+ ӊ rp5 9P7Tښu`:0' ܯ8U| ޯ@(ڍR8mHf> ;BQҭOZnp1Wq8cE1ӫNEA|ΐlD1)Ѵ9^4f &f!va8ɕdYbCu9 ^̤CJZhBh:4EYt11 M4L3gzҙ[)JTC1 (ωZt=sTl ONAk,4"ؗYnd8(}V=(V Ge 3p6s4z,*Xf%*l+Ʊ8AJL݂ ;ƽ!*r JO-&g)AY,39KcJahfb2F4Qh"՝. N)"-)k$W,Cm*Ws!EzL/µu =D$kЧlKӽḧ́N9_LZ8$;]AHYaNhh66s\ (j5!#QSB{]"X CpHg:26a64OWtk4ǿUcw,`$smTਥiך@k 3w ?_"pNF%.J M*A\DvfjnͰ6WSkjZ*RIw `b>V'1Zǘl%MNEfb1L9oS|!];`e4mD1 lH_R^i* K s* +Lie 6Zn8A?A??-)sT3Fd084R9`l֝=EJ,,nRnh0yۨhY@O76U#pPP8@\5̈́S+ WCZtñ+^nL|-Q{(h\Z]iȃ}OrcM-Jp \{: ~ӫ «r?YzweJ^ 1:{ ZTr4lI#1sA}~t>bU\OMCQZEH%vԥIܩPӄY\2:LzUMS} >,{ZIBCT?לkΝts 61srh cmQ\ۂ=и`@Rˇ[1%79"pF((,Ge0y Œʼzq(3*qyϺ~HjNiIu/yI8qθJL)So2 [`꣖G,hZg4iHΐ} &OLưd'~ Sƈ OAΗhr+Iզ(aN G' Φ9Bv<Ƹr  >?hKmQ^R`BAτ8pQEMPXI%Y"7b1wT1 dTim* wf( ݡT竪SEGMM=]M&٨Ɵ?Q_WVUbYS1QءPHz|ͮ? _-*:9Ot 1X _nv&)^y\8P pm@Ne(4aB *ńP$Eԓ̔ZIQD7TSi6%̸ɸ'}J42-ԦDŽVaܔǻ*˲X֩])$FFD]jArޯD*";p#3qKnf+M.U.F3C۰I۶0:ц-Y uK&I&ʖ8 2{0ɻ{$qS(M aEm@Xİ[›[)xtv,ƑZ:7 j ?mne%֬ۇGVGj=sw0dF?SSMtjX;Bh`UN@nco8Ű29ZP}Q =diz* " вc1j@n٩M6̿λKJ# HtPSF\&ٶVEeEwg4+j K8}N˷p7J$Vi.A!:JhbiQjx9d'L}@d/Ql@1.& ۦKwUmKs“P(<S0sD~5:rÅ*g:'9 gE:J gWYW';L^ՒګړGBޚ1L9_߶A lcP+o*WF92dwh H M9ԗn*YurS1jm ~*9ª5ߣyUׇ 5VQ{MV[/ksߜ,O QctC<,W){ug]>l P-=J=`g\2 d,.^MPȹšߐ)b4I4]#NN2I^+qp;msG$TfJSBS A[;SmyN6Aoy;'|Ycۻ;G࿻O;{%?{;o'hr{&a >/N}ښyovX~KR a$GTtLb J}9naa{o nN(FY,$-1'Zx{}zChY1rk8`s3v=5_YOJ&@C >[ڣ Ey;Cp~Se ~PD%vKd$.7xTcǪ8tЇ,n#U+1;}fez~df~+ M4 rSEL,\>lZ=L(*R+b]tSG&+: ux'  NCQ'iω9+h?nEDiX7m ĬzXtx̺<&>ҕ+NB*A^g8}pqL Q)YڜE O0e1Fh%jylp<4pcB470.qBVdJbV`#UvNv١DTE$ŖyHȣQi0  ;oE92[Losy6t`rPHRV/kcQp:r*2 ƟbƱ DLhC^N (Mҥm)opo-Zg*9kMQ!B7?5?UȧbIPȡ#0BC6x<RXkꠣh؀SyPdA/d( 2YüpqY_L.ޕ>Na>$HRB:UqU;$3 ||:n5mH@ e*R)oHDRh)&a8M[K\V"ܳnX#i^~; o@Y*n4 :Z'JYrbD ǃ `ǦagŀHm-RW *^"$R(e9ֹH8/QŅI[\cY?rŕ4RZۂPY>Lj~*c޿CߏŎ#:eu[aA}@<8<l:xUNs*]Ua]̸vP+ġLz d`?PVТ v|C9A8l 3VNh3Cw \xޝ!fTp9/YXg 3+1a9ZGq8Ӥ#`'U7.+E)Li?-y$;. xBZq$|p@UR vݝ7b^C| :9UAUɥRxqw,;*Ti'%)7zhT:;:ΎRTbCA"ge jOg28%G8uSRC]#k3Tě= 1oXI[F>_ GsUB)ZmғjءZK6I|hU8A<.׫O>8B/ G&V1zK&r{{ed؇} V^؟o`, hklZInou} kmkXҟѯ`il &6q Od?9Y :V#aP~[U}9>{]/904&;Kq$&mJس27V 6ϐ5̪7u6aS3& *s9)-(ּ^޲Q{3NGpy/3@g!!y1e1q\D9-&yaOivA-svh,^GNVo+BosWeM McUḰ96q:&[GR7d]*ޔs|׿3{KhD9/JNrˏQWNT[ȦGeqPj>mrummgT7x1@j6yI&_9ڎEݰNkѤmO 6ji;ׯ_>_K9>]Xmj_;pZc/W j怅%mcTX26Ǯ^ <%2*,9&tssIUu30 _J_XdHoO@.:R STCGøGDZܠ=QpLb>1!wY0J|M\Z^#"?(+^_G>"E+K(.Zq>v_66mGIЁ\݁[,0ӣɶ`#R*j E[g3](TU'[`Ѐ$][;IAE0OIO0f D_N:آR5̮Wsu\kE&^b ~ާȥUm3my)pIWJ}K:6|%MI%:͊*υMWySo{5lF 3m>՘sA4  3ƚ{ ֫FV!q@~nx{ex50A2 f76b2kCoEqN\pGhLv|uɝxQj`&o3{T[7m9ߙ. 0h4Emr'sM䠕fp, tJzk\d,}JH 8>"jMp۠ +Z\`7y!|!k{ac r mJT DIs|Ot~!)X,i75\l!g`_'e<{7k3$jAuY!G'Jd'vEմ{o4RoJZ!SY_ x4&L]rdTԍ_mK-r]).+6)O3#Ժ-Nja0'M铬v`$CnyN7?֏GN=0+K૘mkəhH5O^ð糵s $m$3VBsBJ^/)mzS(M1g"1ZL#iX8LJZ](xˍm5ˋ3KhȖڈjsbSX]ͳ܁$q3ۤ7Ȋ8Ż"2y$G0ҩ[M6c gVSDq}jtun<6/هFu;QtZRU;׀zvWS#fyJ@Fic:mX=*,CF,b7nw#heyy\eD`K/s"{7 sYtU J%ɮvs~ƲJBQ(_8A pcXffi@.R0JIAחwvƥط&mz;gmjqLϏl6wj5{7 (Jmg_z]nY8ٜG oJU{l\=-Wi\\jYeCcU^90UB@]D G$Ju5Bs *"YE^w~{xВ>7CMP['|d)v8̹H%|5D\=1A+zG'33q0(\(z+ntQFXy8>d\)2f[i^gQZ"^zҭZv{Zr:ɼ57~ :<)FZ.)I:lʼ?Txɬk$6>7 5k&joisjgTmۤ$n6om 9M>**~FU·z~p׿$B>B7؆5&t ~SR<RIf%y+b^^WJaQNm2-H:PJ`SJ*Fk+\|ryVub9)Nouo>Dͨ]Gv"<4 _~`)^gk_zz^tO:Qu?W!xb~//_^S_Qۜyjg1Eh c_ ܥ3zhuڌK XcblwJLH-ϡۃi4 YMbVjFNT™ S ̌t" -śbM]$B/^ N V;=Vý 9֑un%F5Hn S¹X,;WYJxQ 4V;(K`{[ x ,8(|8< 4tW_RVG4EWUdp7 SνSOŅ}61mFQ6>ߠnC eE:Ԓ.lݴNlLwD&!4r'˿MR]K~xMTdie̫-3[?sb|;>LH&8=j~|za fnp:҃1> b/BU{>w9xZwfq[l{@= ;FJӰ+tGWʏCWb|obTUTP>rWABYtJi⇐',K jDtq#2ivwJ%&Pn~uR[]Y+ `G0 HXsJldIEdI8ALKhfzZ}љl};X˾=Ʈ/ǗSW37ſ }oz7[;&62|QW^ؗw#[D/z5[j=mUm2J74zGg/>z7}껏I}7|ͯ{)w>u,/{#?oݷ<Oio_/3&~Dz3ӝ?zꮏ O^tM-\3'Ͽ剝7||gVV7z>7ܷqUyk-xp_״|[~k]w臯yK;kϽ+m=y{>oOzܛ粛_r=7߿|ⓟ3cU?=L?ϹՏ{Xxݣ{;⯽o۫ㆷτ3G}uuޥ~y}򲷝/|n|__k~^{q'v4򳷔kƎ_3_|?쟜ӟW_w8vs~߽v|KϾᏩ~~mۻ12KnĻ_#J~ } 8o}Vo{qcq7s>~ٝ=/_Wh7o|O^qWֿu͟SG?}Xܑ3vw·_}ϡ/}or-/~wyu5~³Tݺz?mo֋9}=~痑 |mw?\`[ﻠ7?O~ٞ5oc/8/'}ee5tpwsջyNjrϻ/8G%=˟d];_=JarKyʛ_꧖&?U{Yw{\GO9~C6Ͽ׏'~ϑ\۩|i/|֧_ʛ?;wk%.zֽɻ>Gfzoߍgt=msv[9֋ƶv3g7z%[?{ﯯo>EϸRuuȏOы|7'5&W.<=o:zxW;>mzu;zW}h?}8sۓo{r6Ϲ;Gͷ_u?Wo38_}wgf%<:kF~;k枣骉_: nzDǵKޟ_<{]m_ ~Ly Ap1ׇ{錳v{C{ҷO~oxc _6;>/?xv+N?yW0y3Vںs3o"89I?\>֗-%+nd.]uMמ=}7]n|g?pԋo3YKe}[]}Kv~7]vwqW<?]3w}`K׷7?m0g=쏽Cc˴~y?_u;/UO}_J>䃗;`uڛO{>՗1|U񃫽=C깏?{k_̕w/>nǻ~'] …7?rH/~M۟}SG;v^wK}X~POg3n9+~{([W_30=m^kwۿڟ\~~wݴ8yͷ+y07ӿƱ{k5W_/7txٓ}kxgϡ1zGZ뽹'LS#~K7xcq_M?sOYL?~'q3]?izŏv,̏{^]lୗ7_;k>o?>~~潿 k^O}{}g~y [}Ͼ?^W|?~}c3n9o_[0}_~}m?Y=yŖ[xϵUȣ3z2s{>/7>6YrfQ+6Jr,Sʱ/\G"Jg ٘xU"9Y.M=x#2uF;Pѫ C\ zZВ=|!wP!l7=O1Tg6]eˡpT:Xo:U#Z!a3UGg3h0X.ow|p2tXh2exG+ebd عHt,_ǩ5&x6OcAqKzEۼ_':vD?nKm>Id>>Nlrͷ- #-,Ҥm>I|@}l;ԟ?ln.?ߞ8E_umm#&1+|%Sd8W4fsRuʲh(zVUScye^aE=[j)r3E J`i|7\+] և5 f 2j@{V9墾Sd%>9#^w (>5p5&U4'Y#fxtW_dr8? ID;]Bpr!)賁]@sPw [K@?Oʟ>ߴUp%EX^3u\, jK/o⒑ѱ !mqm#WX AmO([A0 I@v-rǂӳv8X(eLTZiU[i'WK zb 4fvkl)o.0 9qϑTI[ʙ 2sK&/˘ 0} DJ=IUyʈ T YNbj9ch<9] %Ŭfl Y \CZ c( Բت SV3wpI}El[J0B&RQS$塰a2%ԀcʀldzF1IT˚F T 9`+fRb#jeSa6QsZX!`af%S2u1c>z@ N0l7Ma;''Ԫ>GOXRX.0/@ϺBmUY7zX!j 1Yzap^ dzX J"mm$"mMtî[- Vc"Z" Yw{BG;$.D"`Ck0tbBm! 7]6FӾ#΁pͻ߹:;Ѧ@SOs)Lݾ+枠HbҸ tƣ Yn:ڔq΄=r;INszIc( hhJv!*X\39#Zͥ|F' _R#?1?x?a ^2Ղ'%|#?rs7Q6ʙ,6#@AF%ͷ6 p(dJ+̨f  Ҟs fŠ Ap1/gы@p2˱~$Ň#U/rFxpa6FO)Z<9=gEd_2psSr2%RL]C0 7YE&,#B7nz?rE·:Y9+Lcyb ;T}f H9Ƶw̬^w8[AhGF Дa [-FCE\D~h f:.ƍv/t#[Դ2}j&/eq-0M5 xVLW8eΖkS**8nT P3\N]]ezxKgVIzUb(SCyImrSim&+t)| {Zћz$3J(<0T@<  `B($d4bUy.sl 'O%!ttY%@7u)T$D;F,䨘s=SI .7:vdݰVQkU '5P8 3l"&eAp#C7_K ~DI5eIXFxrS`W>XYN#ஂu)@(6D [{"+ 63h{@́vdK@#,FlcD`DF>#Nk)wT&I\Y{\N جVh=Ms0/1t&HJ@(d!P~$# +bȤzoAdUkxk-pN3l'Uj{GuS#V@ìCI0Ic, v|}mo@SU8]DIsLA*.ɒ' !nq)2 ^ c$FqD e\Dv nP ;x8H/{&  WTC% ,Etld s&~RJ8`$MTw?:9kKf1i1L'[YosR.oT!g&Hqt#ָ11j11ny5m&Q\0zŒT&Y(}&H[I&'.+MSDBTK]2 a=Wz`ه&m*QfBML.?]5egmd|}<&M_s(=&X͐m]3'o׮"5Oǎx[oS'cKjTbR /|>TJ Fn7EmC ,~0S)er. Ez2-/}MjkX}MzbL,RĒvfR&, l+--MhD_ V4553R,`eN RZx@%跑Fz)MpEt2j5OD0tišΘ^&/t' ?РLx]wl߱)?=mv g{g)2|N yG&&sw{aaDήW+eo|bp*:E8[L֟ؼn<|N&y2;^Tz,P WVd_Zu pkϱ`o:b -TNRi@i*޵k`(H&e >j4od-ڪ|[rWmM |Pc!~faWwLv^i[AMy:ij356R`؏ 2|-K02:aOjv9Cќe[*,״FͰF<.KD-vx,៞աUC1QL54;4kw+}{p)asPESanlmq{ O O O̸p 7hTAzϒPP aPdonS FeT[EpwO9 2(leO-W?ZӎPmN(Go Bâoig?/”jW(Z\qoW|M״1e i`BeacSi/BqP@@ig-M S'bcQBRWt iwMi;1pZlaM3R6# 5m FMǴ{HiDzk:~si\3w|RD,Mm伡n krQc&?A*]''=kx[.^XeA¤(:5Gz!JDj>K5ܶ 5\V|SA&RCr1!_ȍd^[!TT^em„Vf'eZ㯸f@Q%, I%  żf^1D#UF2&Ͱ5\ދX'*VG Q"'|@-i{J%LSÎ $wgPA4q#Ԕj gnhrT5+ص&9+]5(c7F?͸Z\WfF-#]C@vbne Zi\rPO 5YW_ rsB ub-b+_Q~g5 .і4tx&I1N:CU/Ae24bъes"ҡعzP$0'7:㋴^I o i:QOm*U +G'8 J#:[qH$qc N~ sG~zȢF$n9 C$n-B/Kwl0bIÝ8&!yNBP;n:)/Hc測=qO /F8  g] ㎎,,/-*)w$eh%v\@L^vvDL k7bQ[0-K!)͐cr)DYZH.q#; )Pxf,(dЏ]\ \$!iC T^ VzvnD'Ƒ;stG$|9`5l0s7'S6tq/1}u `B{šqu$/J U:bM%HE\e=h]BL-e ڱqBnVA?zx*gLE,O1A 4SpGYg(On#%&ruaW`^H%c1A^sLSNl5=z9ƎC:E\ʔL~ӹ#RʑLT^I/Ky%XˀS,}BSp !J1hS.TVܠܡ;X%D)K]**PB/nKUy,8C6 Y:Y7:5Gw8U͐З+p$BgweO8WfLK;:r@:һGۤ^z8m71Uk>>|?zzX'IE ?M¿f,)n2 1Ltp5E|u~F=L&f2M\~|u/3_kmE(],AW{s<+b bۓv(*RmP$"FX)/0RQ ; =&~1{)@mȒ"_1H}$|JjV~>r$G!CUcZw JPKQcx}mR0Z%{U E9m:O=EOo W}ыB>k7ŅRt+Gf(udK4Mo'y8YE"C/;_ZsKɤY|*"WOx4~$^TFFډ6эQt66:RcB! ;-a1nrDF`FH]$2ޘ!Ӄ#鴏't P%XzlE3/#ݤV-~F2`Y!.`(QomY n`q.2~?HV!aPrQ$N{|8=: Ŗ0k9t1m wζSO;Ȁ +qRTE x)S0&әC/֐)`CA0p!Ąr"?ZBfܱ#ĩJsbF@}̬!.BB-B-ZSP$5Tr' ԅU"0ÇX7W_2*daqi)c|fNfR%T{cʲ&L!PaI֫Fce.XK9\Ʈ 7DžF:iŠϲ1Vp"rl3j @){s @A@AN2~UgZ U7 ̀ut/l~:׍4Guz g5'Zm[_bI+&Ʀıi?Ճ&bTrn7aAjNx$srdׇ8ryzv&Mꆷ!}o}KM(%6JNɞRHDD&v\<ݳqq],6Ԧvsf"np{On,d.wsSF^cw3Gn8!H#.UzDF@ 9alDIG@mD m[.:YNoXdoGvwuSHr:&h]wiBA! ".UfH> lX!k3/%&g, O%~IDoPR5sx7*7'Ux޶/BH ),,әe ~dT/Xz q`aeT[tVG.KLj=mIa'qMuh VZ1qE*D;U&,FxgOz$<KZ,`ܠVh}S ;(PNGIX#~j)f2[&2 'vc4c+ì3G3vS8ɪ Be"l='eh^J)Գ*P 5V-f5;E&>_lODH}.WY'mnwH}k!KRzU(L'/ףJ;x(#45}6Xt憧B9p2F;` p!xIj Ȁ1I \䷊žomcmdgQk;M'UZ&s\͌܅ CUɋsYVn|UwƾfGFdhMqHC)D)fG6 &0=6mFMBԀrz֬ۻbaMqwUU8<7:RB-cE06 {$iV5%r޽0&nF/zjrŗ罕|)0X^K ׈u!]HJ&柄G7ML E8bhiҦF!nJiy!-F;Z BaE:i Q֐_Ddi/[,5y F<"Dx*`(~:cD+n@ύaut@Y/q;wn\=Xe2|Q9V:_6^M\J +l-X}|퍓pHtvrcb&#]IrϹR?PW4ĈVrsh`AJ* QuX!{53KJTړM_p2CT QݪҬbkh?p ^[@PW]~'XC-ѰpFu1xnKjT0cK~۴x[{q:NyJ0:Ň'vh8u?9!_Wd1x|^sb((U 4A\QQpF-]1s|>JC&Q n yX("{Y-)A1@j.Yh&{"g52d+8E(k_5 w iv^`( ׺w#uA:xQj2D9|?vDARY,p%B_ 8u#R UH<C p^]mX:u3bar%+p 襼a/#p(Tc0 V2x᠉KL6RR5MYr9vaZpqxn mQ+FB++fUΆ̖a:(ל @J2&ǬKkMBH!-Y z+ BXc0DՅ)hEdʆV4/h^8'8mZV /(MGNialaqBA_{-^KB Uxayo(V3 b~ h@xX"e GIU=l'YsGsG{\qxa%h'rY ע[1 Ŀp xUAGfdX-(8> s $cL *ơ9Bw#<gaq+_{ U DT3YԤEa,bWZsLU*:B*L vz<6l9`T$ ;pZArE,-=0 x9|Kkۏ7ƈ2Gt G- ;p| ΃%?|he,,C %8짃 QՈi[Hj*H(!o'"˚`);a i[ SML1jmi h V@5!oEҔh'̬~D EE'$t9$tORBT DZfXs''C(J .rP{gE:V5bZXN,H!vQ"jd> ̃xl&e"& xfMn!cX$/"w`yS|SN!|儭Ucg!AR@.}hsI9M#0qg v3-Phj =ؔ&ÕSWjS^< 5P(l%A"g\3Xwm](guڶlnWleRׁT\sFl& h^7c+8fxx < !Op,5%҂れZDvkE0_lz҄^m0{B%@U]\ ENz8󛶌#Y +s\%rHs꫹jrav=Ĥ%o4je :dRPDqde`˜iVeFV,Dl3w8.l3Ng/2s37gP:[Cm:Jg&J}oPĈ3|^Y<(@ǎ$Ǎ%̹gPO:̈́B]m/#1ŜyBa- -E~D~:|0LK,̝\.K PK]_QFrZY4 /,.JۮJ&:vej\V[~IKz0,B:BHa" kRyyQCcAU8h@ã}}>{1K#Y(I .rR$WV+S.+qoKdGAC.c+jجoB߂RSsi=,!2W;c{ N `k,2`GdX̂B *Z&~l%M*y H$Tv hnI&Ķ_FbW:st(fkE|lSX ,@Er;%#8RL ye_rjAX0k S}kɮꨤͪ>!h(dz-q oNq_yIg0F.^Q!kbmWRnq2KPi\to+3@;D%媱Ѐ@H*̦{ `: Ypxk΃V 0M=,d (>8X/0- ^EvBLz*Gl K :֠<-C\<,!AYH[*5+[4wC R`6..jMȎP#bԢMuȐ0鵤ykBcv3nӾZF@HZ :Wn9/Ԍ\+e߾O&HqQ-j).`Hċ^Ί[uaӃ`54 }[Qh@#t@d_C|qEkթxm" ⼧b ryR↰Ni<|K}9Ć*񋥌E NrHh +QFT7&P_׌Lenj"Nhr 6Q[/YգGߪ7?f~XH(%qe|/a lfP^b6|dBP?Y(Sjoe!(>؋2pT -drGTik^uq? Ik_tj`M1bY[CR[ DffhqV?,P Σ65ɛTy18%Z `A RI6W%^&|ZoʏT/[wwP0FB\ ]b&$w?VAɱL%S4IX@MLp('*HEԟ 0"z@NfM&څ t-6sRzrօǶ-NYjèonjL ]aPltWڒ$sqx˽(1.^{;uRps4+kQP)}\}IҮ\h쟱);u p2?1e`^wXIedX:[l/h}wwZHV")~c?:0HByy:les:)Q+rvv ͅɧݎ2P-(Zd!O OnV y׷BΕ.|'蚳aiYE@?upmJyz{R (*+ϊgF>TkL&Σ:x \.|'ۖD0%-1u-%>Y_oNqq2Y.@Ey|8讜=\b,Tbw.WHe)7ZMDH&50E_Jfxhr%=eLiDiY%HSpIQL$MЅ[ gQW?$Us$* bFp!Z.ʫyr" c{j"qީIAYh\.,Q)1@}ӑFC##xeoW)Zҹ &!bcV ԥdg mLU]j}ƌck gYr&}G+DX(\EL3C{ˣoz45RSҺcƙ+qh#O{s3TYMZԎhFRƺ2|Dbg> 2&ZzdRN&HjwA/jQl͹0 ~<6H/h^ ȴ?93eㆪnb=\Imb40yXÉuE\+\ӭ.8I IA6A !"fN,Qn;o=kyPƣ49An1. ԃDuᓕˠQءH,3ڊ[(VYT5 VSE^n-cΡJ;]AzpZqjfP,Qjuj~6T(cg][UcuP'/qLC'jΪIiPz^ ]HDm@z-hx D,Q: lԾee` TҳohxpА9=rk<>7@p&6] ^غyd,PomUTؚ t|/0 Ef*>zIP,7Jbkqv3-F0$ '$\J[ ;8-) [Q}nCoVA3Y +cLqh9xaZ<^#n`-B9s?2:> HL.SE' xr 3*rh ^^M Ta _(UƴΫ!Ktþ٦,w j%%)=(W [e,v΀W+In%^v_P+gk.䡕]o* $El>v?OXlzwce4#2={/-gfJVia[\:,Žê)d_g,*X&\sX.z%&t"yGo]T;.vE=}C f_ZUY(z.Ceȵг 1# FbCΗygYlV UQsKԊAC ć.lQ] "!{=ZR[@a@Sʠ-kF5Nn6\&Qd܈e !P+) kSM@3C8_L(>jjhXXd4u62fq4<;*uG&UsAZ b'r13ZQ:L!pʭ8TҲQ<\i$֊ )/|sʋx]Ë`)"Q." %i*K4#կQ-Nn6b/rK}{@1U)c? oEyTح-9a-yl-`N*\͊BӪh$=h! [x/`VEK|(ZӥFJ 옹[M %fu=^1oRknGdh10ȅ#)*aPC'&P`Cn8[4 hICdyRd`%*dZGRR@l0ĪsrsK j?wƎFMG)u,HD2DFeCuRCNO2UjL}(  E5eo7X`"pZ2͹츳():= : E":as=:FUceY{:wQ<Qk'b7R3Fe~ׁ[<ϺwsfV򡃌kRej"9ІMUF'00r%|Icav$xcdK< 2`wcI .&51tEu'-@x1e_#z%Հ X /LpZ ;81tSHsav-th2)݌*!գ)y`۸q2r An5u߰a'Dr43-j{2ɛh G(茥Q(# ;G#u)ތCQ݁.pC?𶌰=w3tK-C}Zb G>돌 1z fAo xFIs(Ҧ>D,9:S)ǧd2[3靖Lqw)ε)s* `i9<Τk}ilQ=bBH&zDm5YuZ24?:>F搥ܾ&%D>AA,'L\D9jsJ42J+KC ˒uAq@P? HzIߺ!T2+\Ҁ<SxP/CK XHjoK:l? |.hrB2-چbZ!0fe(w`ahS`Z^/r JhVb_6g4<KRb"33ȤYw钟Gc `#?8>߰a;A0$s,)t|I`֖vU/? ONCc`Kuod@B%(0L(b-e":J,<[oLG&ބe,bOne| dy[SwM)k,څcٲgq-S?j"0-@#h8X,Gimm%2%)qNDjYǒ~dR -?ӣ.)S)5'Т\EH¢xq [BJ GjQPat<fMRx-ܡסW“V}% X;_7Fqww~9}|2:r(<ዿ \"&kXV=,Y "E~.q.4alUӞ_H;hq;VwV1V~ͶC8!b~P?6n?j]'FeU:f@\1X6#4 G /HLHmf@(Jޠ)Ы W\>]`h5\ ť@0HP.n99Yq 6Uf`0;~L؂I! +)KG2~ǶbQ{&aL4 ȫ6Fp~PNIZ&(m V5׭kʻHSeUen6m5^ (@k]84}g$=އ WdId'2ku]ic:Xf9%JvWYsgU6*0UҸל53_t~8u++ 9HKÑ@ITsHc`qQ{6 FbFJ$y:9/Z(^dKCq)6N,y?]RaKxO/3.Km~x !LÜNkqWC\gDqq+?J{Jf_7*p _ 6c%~V+"8DE Ȳ*;MCѺΓnDkl[JR\to@26·>ϔ e$&r/ ϗ~7۰O \LHr eR6HR<¥Y*WK Acqȳd5Z:$.^bݧfvZ@/: f;ˑ(Q]$)DY: .Oۓ4k#C0(  $"q )1Z174Ca=S姣ͽV&ߓ [5׸0o 2+0YUcqnh#.JHhijy9qftFb-d]w}رR+b^ `PG$GM VՁK%\ۑ` )`u^٭ٟwIlVrvz0˓ԉ4*8+pSd?Mͭckg7c)U3ͳҍQʟmi8v/ R|un;iEs!-Bc`ˑXCݷ"͜*h12 +eGa{[;U(M›EA9,xbU/{^+i][ڲ}Y9qBEC 蝃}C0qkQ`0A9Kԭ%_8eT5Bh3?&Y5,lrԶEd޶3[%as?}sr&.% ;=F\9jOi{9x8SrQoマKB+H_TOdXdrESr`LQmǑ+EOHl-I|i$l0L^o@&ry\D؇=qX՛N=|iGJ9zuXt<[ >?!ip}5:˥jw!/+5-ɩJmO\N Py s4 "{`k6??7ڍq{R^^{pr}dGW8;g/r{nRKJǘZ6G[^5d u3P [ի\6WT (Df%$Y!ߡD ܠP`FYcJUEx⟥]>Vq#-쬴b tP\4G\9s*ʲ*ZTw+t7qY7A E"v SAR6Fab*986$KsIc(pmH{ gCuBlM;(ap6=]ߨ{xX[X}kӽצ""~|aj%R+D b] ^'Z^r)RX?v3MlӋ|̘ʚrLJR:E^Jowx)s{3@2L~m/r{_L'V5N׍v3y?d 9Ru$H.Q!jžCZej!N4? y Ř.Jousn`۪+&d.Jid9Ys,RH=2m.NV VnK,=)/@*хY6FMkΜ`wl[ZځyJn<Ղ CrREtҬ"vIX,9O!ql~k{݂ 0-f4.0S)>`[ 0ꌐ6Z$XR2dКg`ClM6`.* ƅ@`SN&8@5C*x4 .:&/Ԥ.@:”`-46H3چuꤳ\[n-'^L?B;I%_C&UpqJ|5m#ˆĶ$o\H$HVS+9gįtw\MZ6+%4Sjk@\I;nʼn ɜ`"{+Tl@nEXv;M)Gi@WPM4?85NyGFi}V=b[3BGؐنͳT"#hmz:H/YH*eFN¢^n6ȝE(|ʘ\aK2- R"tw!He=6M.d, )v,QD&Qc7+(KcT .(x!¹@*vb[# b=kZ"p71@X'|κ{?[:ld_e~#LU|Fƭ`߳2Xjx 4ν`Cƣx! &=* ŒƖI?4ҩٻ^Qy([y 8Ħ"MyyaF߀[TƉE|$ڝ9Uo>D egջUNO ͤKnKX~2T]#YG2OXhȷe= Ψ"ԗVe(64QSnsh~`W~C-QEhdlCKSIyFU5c+kfߕ%[}7*bC%?A\XeGhN~]?%r Z9A母 Y|dUۇB^-ԧ/UbC,"]QڋŮ}sR9F ̱cʔzcJ`gՃ6+Y-0Ҋ6T c6iz, 9Ox h=N"v  -͠^gdGVNX~]YXm5+>][/WXӢ͠Kp߹Z[,a#鷠|:3!Nt }uff)t8 >n<1=yi aE ɡk^f0ǩ\]Lq@&%]ZQ)ϒOW>y)dsR˿kg##>xXշ~ =,>w^&?=pD`C2:pvU; g6)=5{ '?A v$).eCPRlrLvVXLr}!!~fͱG5z m杶JJ?oQ Yg8̀+0r=3<i;杷M뵹8LcTxu&ybuHuFPkM?yUq@Vt2/X`x=BL[zd.[+l^ךLh9(_X`^MWoHf>K;|$k]1|4hW*;Q1WN )`J!9rVt<$|YX^31@:*$/5XPdWH1"c0*++ϏB"8'vA}$?}B?nC}/Xg%s z9ŁZ#?8. TkuV#} |S0.gPpKڒMtҝRPҲٖ&mhr.SSTDPpWPQoΙ[{{̙3gΜs̙3wˋξ:p^UZӷ3ɲlfVaZtSoqu߿1βϘ8I))J|~M']ql7+Xu˦>W'~uDKSk^sՔjkb7vOHѶ3^{9n^o׈[\9LXK󯅛g7Gow}Q7[zc՗ovf=t7o#e? _ >3WΤ;unNX0ԩwwjJՓ{{mhO^|gۖ7NsNpe't͙GM;&9ƹmZޏ0{K7|01C|ݐkYLm7뒟[vOYzOSƈUV8m}ޱkv~m7I?{/>xE}wOG޻EO=w۫^|>:䅳l>OgnKqSV.wsoYᣒoNny=.`Q@xjr >_fmزǦo+Vn^+{8c?Nӟq% Kiٵi..|f6-)i;Ɣ{C f^ĉ9=>gqkœǻCykn?ƪ3-kz߼'9Oy1O]f}fυy.xOj_1mv3_+vkƴM_<5s' m)|u_Lc-}/zy?Ӟni[r޼hm]7gzέ_-+6U=מcnVtɃ? 㤳7t}y ӳoj[W|ڣgX{V72zd|;wn>+]]=';ܿkw]toe7?6zG(^=A?8&׋uַ=ё&}?T8mFgⵣ^/>dO߼~pϞ>_o?3ۜ?oo^V%{No߾͢|xA^ ƵznBi)sf y{u+S[;9.u}+ͼt ߸22Y)o7sYVѠ{^C\x*E5v~wW9'{[^h[R>>K&/(:f>ՆodGO19i[F\>{s}+f~㾲7` K;ʗ6}HyM{f~dlyW~KFU*[[j&ҿ{ˠOx/>\pnOkn$ewuo\6KϪ?7EuY.>7uxYoni0kg8#Gj|/>>.rak/Y]xWXq? ֩<<}9eyWr _S 3y7裾7ݝsbus>Pw[Zj1e?n~ܸ K }+c JR{yoK700o))42m8Чܜ;sS07|緕U{O[_ϟ[ nY]Ny3:v7czm ZE |[%y /No >,˳>[v ZNzumm' (sCܾn9{]ʂXSoIY9n}X=)))zl_O5N\7S\)H:% {vK={ 빁^{{u⥽gNy/ڷnMGvQ\xj5/s];O1{.g| ?gKc?ϹgM3bo'/~V|hx޿#'m& >=w}koX2ߤ{fZsNOl5j/4X }zϽ~ه_8e|uZ]gE&;l܍W/8t꫖ >~̋~ꝓ.;OqW.QuI˷dr@{?_baƬEWn}9Mm]ѽ$=?7~03/|`GE/ϧ<;L p(]6==w>/yϿcGg{du7&w {iE:[sʦ^S~= ]o,۸cS O _[TS~e6=?OYuLA[_xuD7_vgx ݙsou>uRi{]eO[RJą^a_օ>ۺ%-xTS&N̸Kn3|wqۊ?{x n\` vϬʞ4cmmT 6 ;q`u}iûL#W>|W˫-n2ustL7av;C+洝;- 4x渲Mnj^zv19sO{Nnki~z .i] {1L=+.j}7y~o<6}ɧo7V߫yo>/.}뿜x^},gGq+3Uo_ekOThu^?U>mI7>GzK^+l~1ma_}mkEcxWAn~ACguβGn{cpO‹*v?2SG|?}m럯ϴ}i|Q{IzNZjG]|fٯO;_ϙʲ[6!ϻ)cROl;S7?QVm[k8і6)cFrv9}g'g{죿̜k|0g[;iO?'U?x1V\ZڃӮ[< 5)EvM=ge?{yeL7/)ѐEso}kj{}?) f;1앥]orXϔ }??ekN]VOSѝF|^ޫÎ^+Y9͓7iO]y]_G"e㤪esn 쬽jP„%Փ=[5oH9uFd߮ {^lfƟRTpi5*ځKc>c׽7~-ˆ5uyoK=ksǙ.ݎ~'xm0ޝCuSzr忟nI?9ط|rk8ǭMܷNj?)kM3SƔt ieSl[-:txIEbtgٲ339ofSKeeqv{vz=;;=+ٳ23zpG/,\AJ;+w+DYzf>(z?>^誇V[꽡ZN*97z]!ù.6fGՖZW#Ǚ04clw8a?Ȗa'?Ӟك::8[|ߞ5(ZgG):I>?@PL)8Eb!Y|- 4zhRSNj:"}@8??[C+E2G_4e%%:(~T?6:]%1@P8.(ԅZ\A>kœ#EWg銅@[[m!*\#&-_EҞyEwTV/qeGfg2bG>~!-K d,t~gPq!GG8Bg|7kK >C D,j "II !@$yCSgdsJ<pjE3,Cl@Jr8ʼ_CN"G-.cz|4y]<|9]D 6{=HⳗRtx_EKZ>v\EiNˁlр%F%!g[C0LAv(XRʤ7HTu++% 8 |5T$rEW=ϵxC J iqU|KZ~y'0E)\2| bzRZ~',! 8@8l%vj0iCl;?Xn^iLXGdy9l2L\ Sq5}6&9U  a&FR) +(P:tl9Fk U.4p^EP+ qB"F6IλC@bEb&WW`sKlC`WŅ.H^7BF (l&b[%:7+3lcBB"xN -hrL UmbaQ(qƤ5PM %: ,UvKUdoؿ_{6~ ,#@e -.̈E , }"!@ː1bM)$~d٣ R0_ B+Nm`eA*hthq2dxbC!JHjCl.UItd6lW-<#;6 BVs`2(򮠻"p'<%J;%i9G@ޑG2|k@Rm\a_Zwx $ßD!xb7{` o1r2GlB M6dQN:qbs!XCF8;=׊ ISA:Nmhg @htTEcgC;-TKU-橝.ICLy.f 92*檄>F_ZH#T$Qxs \‚AX+,"RKt$0_Jj"h*6X q^*_Q\MMG3 fWĚv VCwb`jʍʄ"bL Y]".# Y$JJ_lJ,# +l Hz1TuQ9$JX`cm"Z}0/PauuQŹ**wvm!vjX7K0'g1nj[8Ilx؁dx\MTxL?kLJB]q$f)Ε~~#]*u9,7Fk ; ([Y),XB<}i!N(QB&0Rܞ" Y].ԕ'] -Iud!#`BMdaqfա u\ U28C\)0pb 6N8XBFi]'{ ;H1F)lPQ#HP &T|]&@s,0ထ :1ȑ} w(K|?;Ƚ}CKP'tG4s0Ypءv ˃Z,N7.J(A`ar@U]¡Dv%'^CZX?R11rj)qJxp &'M$#,.?4PErw(9HQN뤢&o`Ji$*r o?3;|QfB`!+dlkziFj7A8nHjf/n<8D˯eSGdFp{0I+U59P[kW˃p]@%9 L,INN`-<C>|Z~;Cp6֌a셀a ^N"desVOCG[F !:u7ɩ OG~&Q .TDM9 :Z*hh#T@P&*5RFi 4 ȨKE D~Ƅg }O@_l"fTP}f,ت`DZغ P vR6&:x^'?QDg"J$) x0:u1b Q ipl[h„-aTԄc`̢lȢ!ǫ*Ռ 5@dk@KIffr0GUd1 Hč҅5䤵`P?hihNpij\{EWH b6~Hd^f.}SXہLō S:CB^6pjCQڴUc] +Q\&c h\$Jk6F~(f7lQtĐ|H6;u Mx@a33A<- 0G[sQ֧n\iBe5 luڈB4ED0F=͍r2Fpi.a'\*,-w_I⢲ ӉP4YO֓ˁl(KlP;>$#tpB&&L\ ArNоF ;QBJ3|Y4c9rIZv"jX0b>C.QȗQ bBeg ıItnbz SԸ0dD7ꇺO9E6z 4+i\.}g7DGaWȸK2bkuJ⍽j@6pMij&v xȬS-.t|lH+)Kv^10{8e *H *U@j.eE5.+2@tVvVJvWDG_2FCG`b@nФx@Uu$qGG廢Bib2Tô2QF%oi)'AhQzv`#3 "G("#RDpHs" Nt 7<+'LO61ِۜʵ6&J.}~%9>V͵2hVh(_^ ,7h<,@ 8U`A]28W5=W}¿ ?=3̣߬'3E&u>)j !Ng_(J:6RO M™࣊毐f|ߖcg͜FƇw8DȘ P땷 UvmpԾY]1(A;AvBCGPG Tэ5[ӹqcq+7I)cD(24>Ow#:Ty:|ө)v^'(g"\W.qm|K- ݔ?n;G6`4l9\a=vmB^L`p*|#VY{%= >^94tLI5f.i?kwmۣN?:F G vp @0AQ&@ OTH4!,5]yщM;4Ԗ$ЁV_i }d}P|kA63GQR[˜p1`c) IIB]W%9l55Rmg%!4!-|X'~\8 OYd]8lmP =~\'} ~,|aqE~&]/c7:X㶒cUS'$һF9k1ƪO09NvC0 fhWN5c`nnf7*`VA!OꪵHM$ɪ RLt'bz\F =ŕiQhzze`C9Mcq!Cn &IaSNS!&Z(]|lz44p$"y3$D?!.8X]udDv" LWD|viCŎzYխݬ(-t97zldd.vusUCt/I.ϻCnGxEPzDH,'mUUHЫ ͆&SRS9hsKB@s]Ԫyp?``jW9^nɩ]蛄DjWgQ@.u(u=JˋCZrhӝ;&ٵued3B \Jh蹃4w^.vhG w73;g)WTʹ{u\kޮg)$WA`SQriu&Ju|fTc/t=Gʫ8 , y/ UC"JJjBB4~m$*1{k| |{Օ[kUoJH_r Y]2LÎTͶGU24Y} u71._>hɘOvyM/'0}A~A*֑ϻE!ڬJ1^ZcL 8#N5ZaƧeL]0z}QYsNCu :W=FHuaN>jR2fSFA^%it'&0jc?$Q,1腆pUqP 7k,nvJC @X'yr jE&Zi(z*cR sQՍ'w"]Ń7QH.%cCB9pRveD-ku .~\H7]E(OFJnn~>$^lRC"+]:}m*e$ RZegŠ`$z.QspGDId(q"h3!S p18Y.HӣȖ(D&0j@iƭ3w4oUc"mPW bpo+]!)i#i]`L$Yzaw+wxٶ_'sb-Vud^cv3X D5t"{ y O ;ŵ׎w+/gp/2G_:~VF~zh^GC>*gh1:4u&8lAi#S@V hb3(StJ PwբI5#9 iP=.6CL-J5I* QwS;87o{t,{Q#}+PoI BO*G͡oPFѠ8#.ƂgnR].o4LSg{nl?(+A ;LxK:> X?9  <,Ovfr|}B*ALEU>jY l@'M )G.|u^XZh0T`>VijKhaM5]ܘRY/B <0A':\a" ]8A (-$impWZ#D'VjVO1-,F:XK\nRo+-у"`,q^~;t.rJT2YK:Yy20l ^F:7LbG)ӓ]ۂV_𧹃2u4Ȕ ([S *g'!qXF!`gڇdĞ!|`VC,]eFr ͼ?5s8HAcVicB1XDjuy, !MnA'O٠l KޔQd|$S+腫 yH !wҗ _vi!3zv% l&SՐBl&ҕcW(7!<c1Ƥȓڠ#MzT& k߅ZKC96x G0pRY0]JA "&$T!。Gj&Dy݁< $K<4u+AsF$PD=p-5~R PCZd!DfkPJ3X`De=E$6Baw A/ *h~u C?m%&»iun"֜ jyvy9Iig,F$(!Q-mi f'c0N< dYfp`l3Z0E# hN<juo-j8N˔*7R(azW'/x6Ǟ3Z=/Ռɔݖ2#jʙ^(̻$y Cras( ,HP-dVzNsdz$KॎX'W 8[= hjDRCtW*/=Mh\ #ĖnR϶!!u,-9N RMX/i3=mj#xNCR,4Hc G5nɣo*~)dTI~ʋ[™<^bRM&*tq65 X"yl d[vFrWZXr~6Jk8Cn&2R .u%ꭽ@'Uu0Bz? /]%(Pl"py0$5*$^pnI5%YrcSLqCTY7$Rg4D7{]m, B&USHV+54W(IT& hU\v iaB6+L%f2yylb ol%ȉ~ΡU*6 VEWʻ ~&64hpI_;X7 1pPc]`kA/CO=CL;V]<3ڸt6b㨛'OλLYfe ϼc+?߂W 2?F_(,wX2y0i$pό ]$$&0bR^` A`fFCq8^z_$E(?BQS k0)B`b~WU q*_uIB%%MLu q=N5J$EB+ȯQJGզP;= 4Yn)dĹK]jabv˜TEǁanF$w-EYoU EU$5UY)qTxHV0D YX5֎Jc-Z$$u(Z"^'1boʖI+X/حQCivL!WA<^&KhEvsrфrذEԦkqOWxH^$7Y;y}!L h.sO!dW$֘AcR󾶜ȩS Q(t"mZE->jY-Y7.ѯa1[}3JIc* \gp,ILݎj֡ˇT( @#,2 󌃍1zj=@GɌ?+N|ET@I"RXNWcu@=!l$N[5E}B MK|\5N'`5^-'M=[$m$,b@*:QI_ruFX63n0֒RuL?BwCAWt$Qg0si9:آ40iV Q6pQ%QO,?bQW}"K3C!̜ w8jU! -溓8ykC~?"\!Q0lBˆye.JQm@'جV̯fXIBDͣ`36% *v"Fڡ0 p7Ъz8E˛ZlGR`EEf` [R!bR([/z#\O&lFȧiB=ЖSacQ%ΚVczV<.f>J 6>T QĴ?iy-tedc&ITt03؍ǡB,,1%ѪGO%q$zkPwgSqȫǒ_'D9h8j0fNY4OҼ4O /j3H [I ok<~`}^!#֣65ڛX.i8pTֿ"7 RADPœduat16&Ic՛D0(/ v={[6 CFQHG4eHm䆏q^tÙ$H񥉨z)#Y>25>R/ ^a \k%)KQv$:YIt8mv9=B~ς'OZ1jIj‘Y+Y]kIiM[j?SI) 6]U7ϟK-ȝ!Y6K!Sb >igU4$!&!d@VIR$$sB,t,&Ei,.)QU|FD6 Dz8=@9%7Adu#yybf- -P DenPH^3HBWV4!1R& e"3$rB#v WPEe$,&cL*"${-ã7'yKuDʃ]"<6 f: Fr .z&V ázXvg 96pajThY|!%$ڲrG^cbf@8W$:`Y\VTQAaOiQ20y&V"0\nI! Z@K)G. q6`Bty\MhOh<v~_?Epg:?I^ukgK'ҏ+F>'6! }5h,ŀ;>8>2u#^bݔ&):)\QC"$\HN_!E8#o l%3æ +^ ,JD!qՆxt4 WĂhYs#Fp |!A 8'<+BHD!<+XIĬIpTcF~W4zlSBhz mE>0> H.i@j5Lìz5B81n!Jcc?Xf| !eӅH8Y}$M1E%Ü%#pd**' kv@2hDC0K9]ZYe҈ȥ=ʰ*w '?VSs:ͻBىEej2pE#ɊJngow^<4d/jOd-eDnĠY+,  cPu^ sJ &dTUbu&j~\Ʉ2'0@iyEeQYY])+K*b 2, v=%Ќ42hI1%YqgTNpR*ɑF6;j(.) /Ej24L9HU]CMtTUxDSвd:J \U.|LJ+Iǃ )q2BPdHD+Y7C/QMf Rccnn_ZA^4L@.Ԧz4ӛ&"I@/ S5ƊJ$We6'$mp{=%}r*RsyC%ҥL A ~YL,8itd NjJIII=g?!o2ڪ8Y004zN<J 1a(V*j]֊m ,KXZꏐ]&|loidУ}5+xATgzIy3&{Th )I V\j;sBv 0p%"0*&p0mdv| S6)1w)깥3 E8 Ȳ,Dr kp ĝ~qh"F^ gPsp'𰏛>)_)R#vI'mrttBd'rk"2,#.F>hͣ~NJ‡"fؙtF:yigdj Q!jue[*}KXJpA\4DKkHKKK3,~L) SmLTԣD)[0JckbqL31;$(H-c 146Kߜ% #`t!ijSgxb8-IS#ڇb\Ț. %m0pLYE?$OR8OD~+!kɎ];CR2`peW?fq*!:R/ XS #a?Sq YbD; E,>#A'ذR"m=/J14gX@|Vzn0fF(.&:S;"fD ',*䀈" ^(E5h=.8b{ Od"SO8 jťZ$ Q+hE._ঙ&DOź6_LYoCc.t1cD)8Jf:]fAyj+sRT)n 1@mj5rmiP V)^q?Ԍy(C -!䬠:)Y!s.M:AcF~s*b,5%MUv[j25*/KyL|џ8c)*i~ F{"MYo2Ha4.g@VAh 8a* J(eITסe"4S . p!G`uPq$7@B P |D,[35\Gyq\`֖&ҁJЃ%bJι< zdsL&JQʯi%X)Zf2\I' x@|X]j@iF#qI[iA'u(>Ѹ(ؙ1%E#PDM 2wMR;B"3F>>`dz#t. 6ҌWw.U#uq #d"hу` 4I[="\#Wff<iS>=,Ih$AqYNYZ06sU z.vJDTc,)G-pdA>g%!`>lEb0Em=MEjcF1k`g2;JNkpօ QԝI xl+)@֥)<8Ӥ?B0qBda*7Zy88覰uy";i`42[ #qc ^1Sߎmx2Ԛ |<݈/Yg@`h'|4SP&3hFʬK\a@!olLoAQÜX6(Qr~"ifV3$ *³sFOfZbQ= ٮ{ S2D iAS^qKK#QD4F<5'9ZiRs""^SY*N O%A9˩w܅°܊^o%ԑDۅ UYN|ܺF`F}IR F]QSUFNH(L(mBhcDlZw|1% ]lU&'sEҲa9:LlNHh:$kK"[(LC˘-Vʇln"4i0SSUCb:|!Q:dLr:p60k@[+,n6(xW85ة p ߀/,MҺ!~s܄%иhbP\jIbHDTjGOTYM'_ڴ˘KHɘ.N|+sB.i,XY9ņHNbLY|D3d>~YD!JZoG~P+jS,] &LL LGvaf$)BkHyOb('r6-5f֋a?H]z&Ȁ9,iL|+٪SmCfL<&z]U0db+eH3b`D2(ݤ Hd nĠUbnQ c#tYfb[Z㴬f検췪 Hd"֝\reki.R2)jAekiBƂSᗯ$'~yj\4.Cj@Dk'tн82255 G< K'H[L0^ PT71临3P[!j3)#m8z9 i -@1`)Y>|RX@e|Ccz5jRKNJ2&\,x #Zo[S(tmɒ0D6<}w^  60~#\| ҏoiXEI+:jNc \;*__{ĕ)a"5ȒeI`clA׵MR֢ר%1}ϯΫ%&sمɀ]U~] wYרLSzt"$?0˹r@66,hlfV3![1xr!n̙6#@"_~8ӋO0 \91U@I|{g2/?a+(?p69wޛ(l#9߂> nU?e, gQZYK]&jEd<;e8%(wk?3~/ p?mEvŕ)`l<1&l1cmb΃mh b|&|H0/9H5Cz1#wN"aeuN1m2AEqI.ƂKy[M,e0g\ᓞ@si }V OJ4d=C]Ac>j1o9IÛZOfrab s˨=grP[+jK+X 9R7$׃QA&0:6ѣ:a2tV^{ƨ.RQL;E,dN/^/(09&Q< rw3ⲪRҍi;:W`loh BpZm:սa9$"rݳ!:^6sQ44Vf6t/6OM2$ʦ8U R5Ѐ|cUa hr"/)`aF((,( T$62^ <g{dlU2F:]/vn1cO @>avy=UU2Kx 2BuKMB:>&EޓgCj)dн 8!GX"7b1ȽP1JT6h x4I|"t}Hj0zb˛FXf1Oڧ'y 3Xg<= ŮZBDsͮ?5<˅cF %Ϸ?^8\ؿhԆ #W3]xT5ؠ/E$-.p_yYt,&KXDK4K@2m/# dz5pޔl˘W,AJS+`;0`Aev얖lNFGP._f}2@"nM1ME0zZn;WXݪ$Ui㮕Φ8 FR!Zb`fUq^}oH;lv )80(Љ.Tfl0\MVz!&3)k2phR1[Ժsr8dbB@wNo1@Ns/7;^E5S7ZyY.?l MY-CAa)SRz@^ ߓZ@ÓPɂ^숦lMKɴ‰y@!XKm羕1:`TrcB 1dW%/ eEBiD᫯N替Ԧ6|\A>v&Og}?[_>Rj6!wmIIS:AIȉ,zCx$f"jO:o曁Đ,oR'ئ"hBn)y0 wj7uWJY톮ݞGW"_(J=R|hm3|sQ`(g6(t\8 00늻T1 dy.uD"nOLTu& ),겻9Uu&O`Ayi,m!pL7W]>]0yuZt'gb !\A+$(ww^^)rt )a21rUNӍ͝Y< z^y*> ްӟ[DyIT_|$ҰG]9JʁQg-~$&{Ў;kN\8{.לfl0 T~nb9UqԩN4|O-Sx7 _wioJos-OeCl!w|7vOK!KyپOFϊp"ʋf:g1J> )u$%wūMXZ#GÈ"Jk~ndҾfNC1ʼn+>:,$Fjd ^W)irZ &Ʀ`XkXl?4wK8rb!#_!aؙXZi'S^-;G`C_HݎD $?($ҽ(zg-=J'$>ҳv>a]z.|ԝߠ<+)A5qeZp;.y7=FX;lrg4NRkyi˭k3Ŝw?F6F簶h!!&* 32fd']%c=Ԛ|`F1=y`>a6A11&O,roC1})o'S1A]aqf1ԗᴯ8J킀ajyWrFXఎFO)~~kmȄ8CxO e*Ov!_C,#>f7շo A8XDl"IH7z^Tea^"l:lmn R `)1'KKb /lue89HRO>̤MVT a$PiLӍ3z[*SM7eSxIp礱(ƲE刺16Bm)[~[~yyV?m/q-Ԕ&F1γ~$Ւo,%-E4S3x; I kM*FN~Iش󰜅nЖ,V.Ljv|eș 7''qQCgj3<yB998/o]#1w}R.tީH Nl,msMVHBUZ ^^Ft(NJ$rk$Gh4TǓ{$ -$W U $ Dս)3hs$3NM&mAx&j,b['mb4`V掗w/3Rky&ZM][ǎ%%"ţ }Dgz)ޤ4^DpmG*N9)qnv^r|Jb{(^NFݨrBv&W[g( \?StwhڃkbM΋c)3ͳ_ҍU_mp`)>-WדC?:nAv˵&꾛;'rҲ{9Vhȩ0<*nFL*qlFqnOm o]sd'cZyNBbf`yRjJ ;9XNxE&C`JlKq&jh3U~MF(8bދ{F\t6M=?Od3t)U+݅ r3xv|&Hk<(ÙZo4) )u8h1ZE@`9gPWq%JirYYP!Y&yU"OEe(|}psV* ?90yġpctFJ!EzѱO ўvdt!_ Ւ}oB!"U]LfYЦٱ跇$6&534a?߈F3s.&  6IMV~y:뇨/C3rU6fE`-8[aCgCL&i+H0L`D&rkɱj{Q H+ x^ Z"t2[͠>? hS2G=U8٢NZnqGo1:>N6љCNJ*tսCtn~&.k;U&'sk?YeV׫O?Vq#vNXoh:(o܌ #·y@eɇB'{q$qjtHi٨?> md'I 8 bj9WZ֕ɤ1Tum=gBlM;(cp.<]vߨ{xX2[X}gս7";#~|a%WjC "Es.RJ@Ak[ooI)RZ߹n3l(0|̆2&%)N&=c"X\z9T CM"o4&/A.0C@ySlfZI:KD8¢^ɝC+2%xؒ!L@caщ ] JLP E1j4I#޴f,Q/DX煐.W6f^a\p3bja }Kt~ 9a*藳Y8iwOdsF=|^)gj7sGT_ٽ &1jm6\^,@DtђrUE4:O,=: aIc˙  F:W7[~Uq:zEZHmhÇ}nӱvE)If ٝ%lnܭ>Dmg5U&H`ͤix7%Meq$>$M6-c㱨XgpFaEaBx&qȠ޻\ W~#žu-Q#qrt:#!إ) Onqf|<Ԥ;pښ໒S[zCE(jPmGl/8XzXCF7BV;YXeGi4D/{ nR)\nzF1C.9,Bٍ>..iKUErbC,2vQ˽=nP}V; FcӴz{V5"Xڂ`5 "llXk]tmX$zEEA' 4`wnLɎVu7<ږ1/ko:0 V7|v1^T_KM`{sA.3.a'MW,=Q y ʋי 8)ӥA}-|p,rtu8A|zc8qCyTH5PSTv's'kti>iAPڕ Eqt돠?lNt[MC#ȨVrZt~ =>Vw^fm~ሊy GqNJk]o8IhS1XOzLOzfSkO@reU!*pFqcP#b8'G24 ?!a)(Y?-V_2b̭7r ׹W7cߙd@ڑ:6:WmlEu9rȰܭELS#p jj<խ<;V2iL>(N/W౿(ky5)y୐L1}C^߆5*83YZE$E?DŽT΢_h/\CUAKKK7vwNRacTǿ|h~Ztk~3_uɴKmqLE|;D*μ=1q^XdI߆6SɅNǵJ/#<\Vd\my]EB/"( kutڪ޽t\ե'S $ۆkVt5R_U6*ɩ9$?Wl*n*_Mۚ8FKԒM"wş w!AAoYCQ32wWE6rp kM$@Ji{%IX j?S+^]_Z[XRŰ a[M:N$/eؔT)Y}#>Ay \n過7BSo-.*ה&9V=-󽻧D9JӉP$_H^ޣJc۽7Ot4R C/gT6Q^j2>.q|_'WA]\DO=/m,U>jB.;5w5pd7\'.>\tU꿜pfr־BBcRP-eD-LUY!̨wG_B_RH¯^xڝ^ 3)^TNq(, ҩ ;p|Ҟ\/lNlauH!x Pؽ<#('܁`΅ŇEŠ3HOYazm4.ly4# KRWbp;Q|Bpyp YN-/v™;?SˊI|(NjY% s>]ly>6.`Ծ^Zvq?nzJ0(,O^u]Zm2,L4{n EH(> ]k~iJ\jWzI}%@=&sM;7'\1c)FNOo}Z-bU;]Ȕ[ksR5Ljxx0aJσf[o}s\Wrg4@GNJM'Qk>KC=w~(QtF _* Au#=3\..|gN)߭hF 8[= ᥱr$յwm&K,c^mI_H08g}=8R 6oVk~x> )%XGS'=8.^dtׅzF7ۺ# v6Y+NBD*WO? Ջ_cѿɱt}]2SX&xT:5)aA?|gYxJkܨ7յކ2nJL>nnZ-nO˫s,>&#"p}}}Z8JE{knv4.14#}dRv>,`@YO:9\4i> Fj_l- [")Z!8"r )()v)Jz4գT ([d UCW_G-hZ3|#!'o8#k7RT U7}=gsX@x dd¯][as :]iv- s^Ed=5j4E"9Iٽd . 6Wlo6v4fċ}Z9G Z@ov臷fNl{1`;\S(L&hXQȞ' k[O3$߽3#0Aj'd^Neyf >&I.n-Si"6Q"(Q;?i}OOoO_""@ņ\.&/ bAxod¬ݔ}*?E1nI!A=z|EcS3 5FwtSԪS8fJ*j_@Q:gF}ݝ ,h'{SYU}|eN:WHbBrD&gݲ\8iڠ7㥞g4-l8<; 2wй ۸Lp}P%)BV%KpOEoOם*6m=`4`~y}lc ް=N~UҨv?.y\Fo{4HѰL G`)(zxloċ6%9/ˋ\)-*/{8 \O45EwڽG{;"Tg8w{m5b=-VJI`%r$80ktI32Nj e3w3Lg4 xQ#9VI $;C%RRgшH<TZDj!jm>=4=ex\i\ uCJy _7Xzwz[5 ɓP,*1/n:~עЌw;wG^>yQʿb&.q\_ߪ~7o| S8OͿ')mcCa O"`P[TU%d`!Eb)j+C $$tm p}_ 0<>Z`RBҒj,<̊EV+&hmW(dE»<┴KWu%X3µdD%>*"8&p Za {5;æg5s5A><+u>~mŎL'AEqD #w ZIjJGB" F2RVb1Xit(esm RŦM(2eTNW۳: 9 3םG9نd ^kmݹ?PE[dN/.l gkY7۟ogٟ 9p=HXML-Hash-LX-0.0603/MANIFEST.SKIP000644 002100 002100 00000000755 11623166253 015324 0ustar00monsmons000000 000000 # Avoid version control files. \B\.git\b # Avoid Makemaker generated and utility files. \bMANIFEST\.bak \bMakefile$ \bblib/ \bMakeMaker-\d \bpm_to_blib\.ts$ \bpm_to_blib$ \bblibdirs\.ts$ # 6.18 through 6.25 generated this # Avoid Module::Build generated and utility files. \bBuild$ \b_build/ # Avoid temp and backup files. ~$ \.old$ \#$ \b\.# \.bak$ # Avoid Devel::Cover files. \bcover_db\b # Avoid local testing/dist files ^dist/ ^makeall\.sh$ ^tmp/ ^Benchmark-Isolated-.* ^bt/ XML-Hash-LX-0.0603/lib/000755 002100 002100 00000000000 11623443777 014176 5ustar00monsmons000000 000000 XML-Hash-LX-0.0603/.gitignore000644 002100 002100 00000000157 11623166253 015412 0ustar00monsmons000000 000000 blib* inc* Makefile Makefile.old Build _build* pm_to_blib* *.tar.gz .lwpcookies XML-Hash-LX-* cover_db bt/lib/*XML-Hash-LX-0.0603/xt/000755 002100 002100 00000000000 11623443777 014063 5ustar00monsmons000000 000000 XML-Hash-LX-0.0603/LICENSE000644 002100 002100 00000000252 11623166253 014423 0ustar00monsmons000000 000000 LICENSE This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. Copyright 2009 Mons Anderson, all rights reserved. XML-Hash-LX-0.0603/Makefile.PL000644 002100 002100 00000000503 11623166253 015367 0ustar00monsmons000000 000000 use inc::Module::Install 0.79; name 'XML-Hash-LX'; all_from 'lib/XML/Hash/LX.pm'; author 'Mons Anderson '; license 'perl'; build_requires 'Test::More'; build_requires 'lib::abs', '0.90'; requires 'XML::LibXML';# , '1.62'; # required DOM-compliant nodeNames auto_provides; auto_install; WriteAll; XML-Hash-LX-0.0603/README000644 002100 002100 00000015661 11623443755 014315 0ustar00monsmons000000 000000 NAME XML::Hash::LX - Convert hash to xml and xml to hash using LibXML SYNOPSIS use XML::Hash::LX; my $hash = xml2hash $xmlstring, attr => '.', text => '~'; my $hash = xml2hash $xmldoc; my $xmlstr = hash2html $hash, attr => '+', text => '#text'; my $xmldoc = hash2html $hash, doc => 1, attr => '+'; # Usage with XML::LibXML my $doc = XML::LibXML->new->parse_string($xml); my $xp = XML::LibXML::XPathContext->new($doc); $xp->registerNs('rss', 'http://purl.org/rss/1.0/'); # then process xpath for ($xp->findnodes('//rss:item')) { # and convert to hash concrete nodes my $item = xml2hash($_); print Dumper+$item } DESCRIPTION This module is a companion for "XML::LibXML". It operates with LibXML objects, could return or accept LibXML objects, and may be used for easy data transformations It is faster in parsing then XML::Simple, XML::Hash, XML::Twig and of course much slower than XML::Bare ;) It is faster in composing than XML::Hash, but slower than XML::Simple Parse benchmark: Rate Simple Hash Twig Hash::LX Bare Simple 11.3/s -- -2% -16% -44% -97% Hash 11.6/s 2% -- -14% -43% -97% Twig 13.5/s 19% 16% -- -34% -96% Hash::LX 20.3/s 79% 75% 51% -- -95% Bare 370/s 3162% 3088% 2650% 1721% -- Compose benchmark: Rate Hash Hash::LX Simple Hash 49.2/s -- -18% -40% Hash::LX 60.1/s 22% -- -26% Simple 81.5/s 66% 36% -- Benchmark was done on EXPORT "xml2hash" and "hash2xml" are exported by default :inject Inject toHash method in the namespace of XML::LibXML::Node and allow to call it on any subclass of XML::LibXML::Node directly By default is disabled use XML::Hash::LX ':inject'; my $doc = XML::LibXML->new->parse_string($xml); my $hash = $doc->toHash(%opts); FUNCTIONS xml2hash $xml, [ OPTIONS ] XML could be XML::LibXML::Document, XML::LibXML::DocumentPart or string hash2xml $hash, [ doc => 1, ] [ OPTIONS ] Id "doc" option is true, then returned value is XML::LibXML::Document, not string OPTIONS Every option could be passed as arguments to function or set as global variable in "XML::Hash::LX" namespace %XML::Hash::LX::X2H Options respecting convertations from xml to hash order [ = 0 ] Strictly keep the output order. When enabled, structures become more complex, but xml could be completely reverted attr [ = '-' ] Attribute prefix => { node => { -attr => "test" } } text [ = '#text' ] Key name for storing text text => { node => { sub => '', '#text' => "test" } } join [ = '' ] Join separator for text nodes, splitted by subnodes Ignored when "order" in effect # default: xml2hash( 'Test1Test2' ) : { item => { sub => '', '~' => 'Test1Test2' } }; # global $XML::Hash::LX::X2H{join} = '+'; xml2hash( 'Test1Test2' ) : { item => { sub => '', '~' => 'Test1+Test2' } }; # argument xml2hash( 'Test1Test2', join => '+' ) : { item => { sub => '', '~' => 'Test1+Test2' } }; trim [ = 1 ] Trim leading and trailing whitespace from text nodes cdata [ = undef ] When defined, CDATA sections will be stored under this key # cdata = undef => { node => 'test' } # cdata = '#' => { node => { '#' => 'test' } } comm [ = undef ] When defined, comments sections will be stored under this key When undef, comments will be ignored # comm = undef => { node => { sub => '' } } # comm = '/' => { node => { sub => '', '/' => 'comm' } } $XML::Hash::LX::X2A [ = 0 ] Global array casing Ignored when "X2H{order}" in effect As option should be passed as xml2hash $xml, array => 1; Effect: # $X2A = 0 => { node => { sub => '' } } # $X2A = 1 => { node => [ { sub => [ '' ] } ] } %XML::Hash::LX::X2A By element array casing Ignored when "X2H{order}" in effect As option should be passed as xml2hash $xml, array => [ nodes list ]; Effect: # %X2A = () => { node => { sub => '' } } # %X2A = ( sub => 1 ) => { node => { sub => [ '' ] } } %XML::Hash::LX::H2X Options respecting convertations from hash to xml encoding [ = 'utf-8' ] XML output encoding attr [ = '-' ] Attribute prefix { node => { -attr => "test", sub => 'test' } } test text [ = '#text' ] Key name for storing text { node => { sub => '', '#text' => "test" } } text # or text # order of keys is not predictable trim [ = 1 ] Trim leading and trailing whitespace from text nodes # trim = 1 { node => { sub => [ ' ', 'test' ], '#text' => "test" } } testtest # trim = 0 { node => { sub => [ ' ', 'test' ], '#text' => "test" } } test test cdata [ = undef ] When defined, such key elements will be saved as CDATA sections # cdata = undef { node => { '#' => 'test' } } => <#>test # it's bad ;) # cdata = '#' { node => { '#' => 'test' } } => comm [ = undef ] When defined, such key elements will be saved as comment sections # comm = undef { node => { '/' => 'test' } } => test # it's very bad! ;) # comm = '/' { node => { '/' => 'test' } } => BUGS None known SEE ALSO * XML::Parser::Style::EasyTree With default settings should produce the same output as this module. Settings are similar by effect AUTHOR Mons Anderson, "" COPYRIGHT & LICENSE Copyright 2009 Mons Anderson, all rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. XML-Hash-LX-0.0603/xt/99-dist.t000644 002100 002100 00000000702 11623166253 015440 0ustar00monsmons000000 000000 #!/usr/bin/perl use lib::abs '../lib'; use Test::More; use Test::Dist; use Test::NoWarnings; chdir lib::abs::path('..'); Test::Dist::dist_ok( run => 1, '+' => 1, skip => [qw(prereq podcover)], kwalitee => { req => [qw( has_separate_license_file has_example metayml_has_provides metayml_declares_perl_version uses_test_nowarnings has_version_in_each_file )], }, prereq => [ undef,undef, [qw( Test::Pod Test::Pod::Coverage )], ], ); XML-Hash-LX-0.0603/lib/XML/000755 002100 002100 00000000000 11623443777 014636 5ustar00monsmons000000 000000 XML-Hash-LX-0.0603/lib/XML/Hash/000755 002100 002100 00000000000 11623443777 015521 5ustar00monsmons000000 000000 XML-Hash-LX-0.0603/lib/XML/Hash/LX.pm000644 002100 002100 00000032443 11623443753 016402 0ustar00monsmons000000 000000 package XML::Hash::LX; use 5.006002; use strict; use warnings; use XML::LibXML (); our $PARSER = XML::LibXML->new(); sub _croak { require Carp; goto &Carp::croak } sub import { my $me = shift; no strict 'refs'; my %e = ( xml2hash => 1, hash2xml => 1, ':inject' => 0 ); if (@_) { %e = map { $_=>1 } @_ } *{caller().'::xml2hash'} = \&xml2hash if delete $e{xml2hash}; *{caller().'::hash2xml'} = \&hash2xml if delete $e{hash2xml}; if ( delete $e{':inject'} ) { unless (defined &XML::LibXML::Node::toHash) { *XML::LibXML::Node::toHash = \&xml2hash; } } _croak "@{[keys %e]} is not exported by $me" if %e; } =head1 NAME XML::Hash::LX - Convert hash to xml and xml to hash using LibXML =cut our $VERSION = '0.0603'; =head1 SYNOPSIS use XML::Hash::LX; my $hash = xml2hash $xmlstring, attr => '.', text => '~'; my $hash = xml2hash $xmldoc; my $xmlstr = hash2html $hash, attr => '+', text => '#text'; my $xmldoc = hash2html $hash, doc => 1, attr => '+'; # Usage with XML::LibXML my $doc = XML::LibXML->new->parse_string($xml); my $xp = XML::LibXML::XPathContext->new($doc); $xp->registerNs('rss', 'http://purl.org/rss/1.0/'); # then process xpath for ($xp->findnodes('//rss:item')) { # and convert to hash concrete nodes my $item = xml2hash($_); print Dumper+$item } =head1 DESCRIPTION This module is a companion for C. It operates with LibXML objects, could return or accept LibXML objects, and may be used for easy data transformations It is faster in parsing then L, L, L and of course much slower than L ;) It is faster in composing than L, but slower than L Parse benchmark: Rate Simple Hash Twig Hash::LX Bare Simple 11.3/s -- -2% -16% -44% -97% Hash 11.6/s 2% -- -14% -43% -97% Twig 13.5/s 19% 16% -- -34% -96% Hash::LX 20.3/s 79% 75% 51% -- -95% Bare 370/s 3162% 3088% 2650% 1721% -- Compose benchmark: Rate Hash Hash::LX Simple Hash 49.2/s -- -18% -40% Hash::LX 60.1/s 22% -- -26% Simple 81.5/s 66% 36% -- Benchmark was done on L =head1 EXPORT C and C are exported by default =head2 :inject Inject toHash method in the namespace of L and allow to call it on any subclass of L directly By default is disabled use XML::Hash::LX ':inject'; my $doc = XML::LibXML->new->parse_string($xml); my $hash = $doc->toHash(%opts); =head1 FUNCTIONS =head2 xml2hash $xml, [ OPTIONS ] XML could be L, L or string =head2 hash2xml $hash, [ doc => 1, ] [ OPTIONS ] Id C option is true, then returned value is L, not string =head1 OPTIONS Every option could be passed as arguments to function or set as global variable in C namespace =head2 %XML::Hash::LX::X2H Options respecting convertations from xml to hash =over 4 =item order [ = 0 ] B keep the output order. When enabled, structures become more complex, but xml could be completely reverted =item attr [ = '-' ] Attribute prefix => { node => { -attr => "test" } } =item text [ = '#text' ] Key name for storing text text => { node => { sub => '', '#text' => "test" } } =item join [ = '' ] Join separator for text nodes, splitted by subnodes Ignored when C in effect # default: xml2hash( 'Test1Test2' ) : { item => { sub => '', '~' => 'Test1Test2' } }; # global $XML::Hash::LX::X2H{join} = '+'; xml2hash( 'Test1Test2' ) : { item => { sub => '', '~' => 'Test1+Test2' } }; # argument xml2hash( 'Test1Test2', join => '+' ) : { item => { sub => '', '~' => 'Test1+Test2' } }; =item trim [ = 1 ] Trim leading and trailing whitespace from text nodes =item cdata [ = undef ] When defined, CDATA sections will be stored under this key # cdata = undef => { node => 'test' } # cdata = '#' => { node => { '#' => 'test' } } =item comm [ = undef ] When defined, comments sections will be stored under this key When undef, comments will be ignored # comm = undef => { node => { sub => '' } } # comm = '/' => { node => { sub => '', '/' => 'comm' } } =back =head2 $XML::Hash::LX::X2A [ = 0 ] Global array casing Ignored when C in effect As option should be passed as xml2hash $xml, array => 1; Effect: # $X2A = 0 => { node => { sub => '' } } # $X2A = 1 => { node => [ { sub => [ '' ] } ] } =head2 %XML::Hash::LX::X2A By element array casing Ignored when C in effect As option should be passed as xml2hash $xml, array => [ nodes list ]; Effect: # %X2A = () => { node => { sub => '' } } # %X2A = ( sub => 1 ) => { node => { sub => [ '' ] } } =cut our $X2A = 0; our %X2A = (); our %X2H; %X2H = ( order => 0, attr => '-', text => '#text', join => '', trim => 1, cdata => undef, comm => undef, #cdata => '#', #comm => '//', %X2H, # also inject previously user-defined options ); sub _x2h { my $doc = shift; my $res; if ($doc->hasChildNodes or $doc->hasAttributes) { if ($X2H{order}) { $res = []; my $attr = {}; for ($doc->attributes) { #warn " .> ".$_->nodeName.'='.$_->getValue; $attr->{ $X2H{attr} . $_->nodeName } = $_->getValue; } push @$res, $attr if %$attr; } else { $res = {}; for ($doc->attributes) { #warn " .> ".$_->nodeName.'='.$_->getValue; $res->{ $X2H{attr} . $_->nodeName } = $_->getValue; } } for ($doc->childNodes) { my $ref = ref $_; my $nn; if ($ref eq 'XML::LibXML::Text') { $nn = $X2H{text} } elsif ($ref eq 'XML::LibXML::CDATASection') { $nn = defined $X2H{cdata} ? $X2H{cdata} : $X2H{text}; } elsif ($ref eq 'XML::LibXML::Comment') { $nn = defined $X2H{comm} ? $X2H{comm} : next; } else { $nn = $_->nodeName; } my $chld = _x2h($_); if ($X2H{order}) { if ($nn eq $X2H{text}) { push @{ $res }, $chld if length $chld; } else { push @{ $res }, { $nn => $chld }; } } else { if (( $X2A or $X2A{$nn} ) and !$res->{$nn}) { $res->{$nn} = [] } if (exists $res->{$nn} ) { #warn "Append to $res->{$nn}: $nn $chld"; $res->{$nn} = [ $res->{$nn} ] unless ref $res->{$nn} eq 'ARRAY'; push @{$res->{$nn}}, $chld if defined $chld; } else { if ($nn eq $X2H{text}) { $res->{$nn} = $chld if length $chld; } else { $res->{$nn} = $chld; } } } } if($X2H{order}) { #warn "Ordered mode, have res with ".(0+@$res)." children = @$res"; return $res->[0] if @$res == 1; } else { if (defined $X2H{join} and exists $res->{ $X2H{text} } and ref $res->{ $X2H{text} }) { $res->{ $X2H{text} } = join $X2H{join}, grep length, @{ $res->{ $X2H{text} } }; } delete $res->{ $X2H{text} } if $X2H{trim} and keys %$res > 1 and exists $res->{ $X2H{text} } and !length $res->{ $X2H{text} }; return $res->{ $X2H{text} } if keys %$res == 1 and exists $res->{ $X2H{text} }; } } else { $res = $doc->textContent; if ($X2H{trim}) { $res =~ s{^\s+}{}s; $res =~ s{\s+$}{}s; } } $res; } sub xml2hash($;%) { my $doc = shift; defined $doc or _croak("Called xml2hash on undef"),return; my %opts = @_; my $arr = delete $opts{array}; local $X2A = 1 if defined $arr and !ref $arr; local @X2A{@$arr} = (1)x@$arr if defined $arr and ref $arr; local @X2H{keys %opts} = values %opts if @_; $doc = $PARSER->parse_string($doc) if !ref $doc; #use Data::Dumper; #warn Dumper \%X2H; my $root = $doc->isa('XML::LibXML::Document') ? $doc->documentElement : $doc; return { scalar $root->nodeName => $X2A || $X2A{$root->nodeName} ? [ _x2h($root) ] : _x2h($root), }; } =head2 %XML::Hash::LX::H2X Options respecting convertations from hash to xml =over 4 =item encoding [ = 'utf-8' ] XML output encoding =item attr [ = '-' ] Attribute prefix { node => { -attr => "test", sub => 'test' } } test =item text [ = '#text' ] Key name for storing text { node => { sub => '', '#text' => "test" } } text # or text # order of keys is not predictable =item trim [ = 1 ] Trim leading and trailing whitespace from text nodes # trim = 1 { node => { sub => [ ' ', 'test' ], '#text' => "test" } } testtest # trim = 0 { node => { sub => [ ' ', 'test' ], '#text' => "test" } } test test =item cdata [ = undef ] When defined, such key elements will be saved as CDATA sections # cdata = undef { node => { '#' => 'test' } } => <#>test # it's bad ;) # cdata = '#' { node => { '#' => 'test' } } => =item comm [ = undef ] When defined, such key elements will be saved as comment sections # comm = undef { node => { '/' => 'test' } } => test # it's very bad! ;) # comm = '/' { node => { '/' => 'test' } } => =back =cut our %H2X; %H2X = ( %X2H, #attr => '-', #text => '~', #trim => 1, # join => '+', # useless %H2X, ); our $AL = length $H2X{attr}; our $hd = '/'; sub _h2x { @_ or return; my ($data,$parent) = @_; #warn "> $d"; return unless defined $data; if ( !ref $data ) { if ($H2X{trim}) { $data =~ s/^\s+//s; $data =~ s/\s+$//s; #return unless length($data); } return XML::LibXML::Text->new($data) }; my @rv; if (ref $data eq 'ARRAY') { #warn "Map @$data"; @rv = map _h2x($_,$parent), @$data; } elsif (ref $data eq 'HASH') { for (keys %$data) { #warn "$_ $data->{$_}"; #next if !defined $data->{$_} or ( !ref $data->{$_} and !length $data->{$_} ); # What may be empty ? # - attribute # - node # - comment # Skip empty: text, cdata my $cdata_or_text; if ($_ eq $H2X{text}) { $cdata_or_text = 'XML::LibXML::Text'; } elsif (defined $H2X{cdata} and $_ eq $H2X{cdata}) { $cdata_or_text = 'XML::LibXML::CDATASection'; } if (0) {} elsif($cdata_or_text) { push @rv, map { defined($_) ? do { $H2X{trim} and s/(?:^\s+|\s+$)//sg; $H2X{trim} && !length($_) ? () : $cdata_or_text->new( $_ ) } : (), } ref $data->{$_} ? @{ $data->{$_} } : $data->{$_}; } elsif (defined $H2X{comm} and $_ eq $H2X{comm}) { push @rv, map XML::LibXML::Comment->new(defined $_ ? $_ : ''), ref $data->{$_} ? @{ $data->{$_} } : $data->{$_}; } elsif (substr($_,0,$AL) eq $H2X{attr} ) { if ($parent) { $parent->setAttribute( substr($_,1),defined $data->{$_} ? $data->{$_} : '' ); } else { warn "attribute $_ without parent" } } elsif ( !defined $data->{$_} or ( !ref $data->{$_} and !length $data->{$_} ) ) { push @rv,XML::LibXML::Element->new($_); } else { local $hd = $hd.'/'.$_; my $node = XML::LibXML::Element->new($_); #warn ("$hd << ".$_->nodeName), $node->appendChild($_) for _h2x($data->{$_},$node); push @rv,$node; } } } elsif (ref $data eq 'SCALAR') { # RAW my $node = eval { XML::LibXML->new->parse_string($$data) } or _croak "Malformed raw data on $hd: $@"; return $node->documentElement; } elsif (ref $data eq 'REF') { # LibXML Node if (ref $$data and eval{ $$data->isa('XML::LibXML::Node') }) { return $$data->cloneNode(1); } elsif ( ref $$data and do { no strict 'refs'; exists ${ ref($$data).'::' }{'(""'} } ) { return XML::LibXML::Text->new( "$$data" ); } else { _croak ("Bad reference ".ref( $$data ).": <$$data> on $hd"); } } elsif ( do { no strict 'refs'; exists ${ ref($data).'::' }{'(""'} } ) { # have string overload return XML::LibXML::Text->new( "$data" ); } elsif (ref $data and eval{ $data->isa('XML::LibXML::Node') }) { return $data->cloneNode(1); } else { _croak "Bad reference ".ref( $data ).": <$data> on $hd"; } #warn "@rv"; return wantarray ? @rv : $rv[0]; } sub hash2xml($;%) { #warn "hash2xml(@_) from @{[ (caller)[1,2] ]}"; my $hash = shift; my %opts = @_; my $str = delete $opts{doc} ? 0 : 1; my $encoding = delete $opts{encoding} || delete $opts{enc} || 'utf-8'; my $doc = XML::LibXML::Document->new('1.0', $encoding); local @H2X{keys %opts} = values %opts if @_; local $AL = length $H2X{attr}; #use Data::Dumper; #warn Dumper \%H2X; my $root = _h2x($hash); $doc->setDocumentElement($root); return $str ? $doc->toString : $doc; } =head1 BUGS None known =head1 SEE ALSO =over 4 =item * L With default settings should produce the same output as this module. Settings are similar by effect =back =head1 AUTHOR Mons Anderson, C<< >> =head1 COPYRIGHT & LICENSE Copyright 2009 Mons Anderson, all rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut 1; # End of XML::Hash::LX XML-Hash-LX-0.0603/t/03-no-inject.t000644 002100 002100 00000001074 11623166253 016157 0ustar00monsmons000000 000000 #!/use/bin/perl -w use strict; use Test::More; BEGIN { my $add = 0; eval {require Test::NoWarnings;Test::NoWarnings->import; ++$add; 1 } or diag "Test::NoWarnings missed, skipping no warnings test"; plan tests => 2 + $add; } use lib::abs '../lib'; use XML::LibXML; use XML::Hash::LX; our $xml = q{ first a mid b last }; my $doc = XML::LibXML->new->parse_string($xml); ok !$doc->can('toHash'), '! doc->toHash'; ok !$doc->documentElement->can('toHash'), '! elm->toHash'; XML-Hash-LX-0.0603/t/02-inject.t000644 002100 002100 00000001245 11623166253 015544 0ustar00monsmons000000 000000 #!/use/bin/perl -w use strict; use Test::More; BEGIN { my $add = 0; eval {require Test::NoWarnings;Test::NoWarnings->import; ++$add; 1 } or diag "Test::NoWarnings missed, skipping no warnings test"; plan tests => 3 + $add; } use lib::abs '../lib'; use XML::LibXML; use XML::Hash::LX ':inject'; use XML::Hash::LX ':inject'; # duplicate call shouldn't produce warning our $xml = q{ first a mid b last }; my $doc = XML::LibXML->new->parse_string($xml); ok $doc->can('toHash'), 'doc->toHash'; ok $doc->documentElement->can('toHash'), 'elm->toHash'; ok ref $doc->toHash, 'hash'; XML-Hash-LX-0.0603/t/pod-coverage.t000644 002100 002100 00000000615 11623443753 016427 0ustar00monsmons000000 000000 #!/usr/bin/env perl -w use strict; use Test::More; eval "use Test::Pod::Coverage 1.08; use Pod::Coverage 0.18; 1" or diag($@), plan skip_all => "Test::Pod::Coverage 1.08 and Pod::Coverage 0.18 required for testing POD coverage"; all_pod_coverage_ok(); exit 0; require Test::Pod::Coverage; # hack for kwalitee require Test::NoWarnings; __END__ print "1..1\n"; print "ok 1 - No coverage yet\n"; XML-Hash-LX-0.0603/t/00-load.t000644 002100 002100 00000000527 11623166253 015207 0ustar00monsmons000000 000000 #!/usr/bin/env perl -w use strict; use Test::More; use lib::abs '../lib'; BEGIN { my $w = 0; eval {require Test::NoWarnings;Test::NoWarnings->import; 1} and $w = 1; plan tests => 2+$w; use_ok( 'XML::Hash::LX' ); use_ok( 'XML::Hash::LX', 'xml2hash', 'hash2xml' ); }; diag( "Testing XML::Hash::LX $XML::Hash::LX::VERSION, Perl $], $^X" ); XML-Hash-LX-0.0603/t/pod.t000644 002100 002100 00000000512 11623443753 014632 0ustar00monsmons000000 000000 #!/usr/bin/env perl -w use strict; use Test::More; use lib::abs "../lib"; BEGIN { my $lib = lib::abs::path( ".." ); chdir $lib or plan skip_all => "Can't chdir to dist $lib"; } eval "use Test::Pod 1.22; 1" or plan skip_all => "Test::Pod 1.22 required for testing POD"; all_pod_files_ok(); exit 0; require Test::NoWarnings; XML-Hash-LX-0.0603/t/01-conv.t000644 002100 002100 00000017261 11623167703 015242 0ustar00monsmons000000 000000 #!/use/bin/perl -w use strict; use Test::More; BEGIN { my $add = 0; eval {require Test::NoWarnings;Test::NoWarnings->import; ++$add; 1 } or diag "Test::NoWarnings missed, skipping no warnings test"; plan tests => 31 + $add; } use lib::abs '../lib'; use XML::Hash::LX; use Data::Dumper (); sub DUMP() { 0 } sub dd ($) { Data::Dumper->new([$_[0]])->Indent(0)->Terse(1)->Quotekeys(0)->Useqq(1)->Purity(1)->Dump } our (%X2H,%X2A,%H2X); *X2H = \%XML::Hash::LX::X2H; *X2A = \%XML::Hash::LX::X2A; *H2X = \%XML::Hash::LX::H2X; # Parsing our $xml1 = q{ a mid b last }; our $xml2 = q{ first & mid & last }; our $xml3 = q{ first & x & last }; our $data; { is_deeply $data = xml2hash($xml1), {root => {'-at' => 'key',nest => {'#text' => 'firstmidlast',vv => '',v => ['a',{'-at' => 'a','#text' => 'b'}]}}}, 'default (1)' or diag dd($data),"\n"; } { is_deeply $data = xml2hash($xml1, cdata => '#cdata'), {root => {'-at' => 'key',nest => {'#cdata' => 'first','#text' => 'midlast',vv => '',v => ['a',{'-at' => 'a','#text' => 'b'}]}}}, 'default (1)' or diag dd($data),"\n"; } { is_deeply $data = xml2hash($xml2), {root => {'-at' => 'key',nest => 'first & mid & last'}}, 'default (2)' or diag dd($data),"\n"; } { is_deeply $data = xml2hash($xml3), {root => {'-at' => 'key',nest => {'#text' => 'first && last',v => 'x'}}}, 'default (3)' or diag dd($data),"\n"; } { is_deeply $data = xml2hash($xml2, join => '+'), {root => {'-at' => 'key',nest => 'first & mid & last'}}, 'join => + (2)' or diag dd($data),"\n"; } { local $X2H{join} = '+'; is_deeply $data = xml2hash($xml2), {root => {'-at' => 'key',nest => 'first & mid & last'}}, 'X2H.join = + (2)' or diag dd($data),"\n"; } { is_deeply $data = xml2hash($xml3, join => '+'), {root => {'-at' => 'key',nest => { '#text' => 'first &+& last', v => 'x' } }}, 'join => + (3)' or diag dd($data),"\n"; } { local $X2H{join} = '+'; is_deeply $data = xml2hash($xml3), {root => {'-at' => 'key',nest => { '#text' => 'first &+& last', v => 'x' } }}, 'X2H.join = + (3)' or diag dd($data),"\n"; } { local $X2A{root} = 1; is_deeply $data = xml2hash($xml1), {root => [{'-at' => 'key',nest => {'#text' => 'firstmidlast',vv => '',v => ['a',{'-at' => 'a','#text' => 'b'}]}}]}, 'X2A.root (1)', or print dd($data),"\n"; } { is_deeply $data = xml2hash($xml1, array => ['root']), {root => [{'-at' => 'key',nest => {'#text' => 'firstmidlast',vv => '',v => ['a',{'-at' => 'a','#text' => 'b'}]}}]}, 'array => root (1)', or diag dd($data),"\n"; } { local $X2A{nest} = 1; is_deeply $data = xml2hash($xml1), {root => {'-at' => 'key',nest => [{'#text' => 'firstmidlast',vv => '',v => ['a',{'-at' => 'a','#text' => 'b'}]}]}}, 'X2A.nest (1)', or diag dd($data),"\n"; } { is_deeply $data = xml2hash($xml1, array => ['nest']), {root => {'-at' => 'key',nest => [{'#text' => 'firstmidlast',vv => '',v => ['a',{'-at' => 'a','#text' => 'b'}]}]}}, 'array => nest (1)', or diag dd($data),"\n"; } { is_deeply $data = xml2hash($xml1, array => 1), {root => [{'-at' => 'key',nest => [{'#text' => 'firstmidlast',vv => [''],v => ['a',{'-at' => 'a','#text' => 'b'}]}]}]}, 'array => 1 (1)', or diag dd($data),"\n"; } =for rem hash casting is useless and not implemented { is_deeply $data = xml2hash($xml1, hash => ['vv'] ), {root => {'-at' => 'key',nest => {'#text' => 'firstmidlast',vv => {'#text' => ''},v => ['a',{'-at' => 'a','#text' => 'b'}]}}}, 'hash => vv (1)', or diag dd($data),"\n"; } { is_deeply $data = xml2hash($xml1, hash => 1), {root => {'-at' => 'key',nest => {'#text' => 'firstmidlast',vv => {'#text' => ''},v => [{ '#text' => 'a'},{'-at' => 'a','#text' => 'b'}]}}}, 'hash => 1 (1)', or diag dd($data),"\n"; } =cut { is_deeply $data = xml2hash($xml1, attr => '+'), {root => {'+at' => 'key',nest => {'#text' => 'firstmidlast',vv => '',v => ['a',{'+at' => 'a','#text' => 'b'}]}}}, 'attr => + (1)' or diag dd($data),"\n"; } { local $X2H{attr} = '+'; is_deeply $data = xml2hash($xml1), {root => {'+at' => 'key',nest => {'#text' => 'firstmidlast',vv => '',v => ['a',{'+at' => 'a','#text' => 'b'}]}}}, 'X2H.attr = + (1)' or diag dd($data),"\n"; } { is_deeply $data = xml2hash($xml1, text => ''), {root => {'-at' => 'key',nest => {'' => 'firstmidlast',vv => '',v => ['a',{'-at' => 'a','' => 'b'}]}}}, 'text => "" (1)' or diag dd($data),"\n"; } { local $X2H{text} = ''; is_deeply $data = xml2hash($xml1), {root => {'-at' => 'key',nest => {'' => 'firstmidlast',vv => '',v => ['a',{'-at' => 'a','' => 'b'}]}}}, 'X2H.text = "" (1)' or diag dd($data),"\n"; } { is_deeply $data = xml2hash($xml1, join => ' '), {root => {'-at' => 'key',nest => {'#text' => 'first mid last',vv => '',v => ['a',{'-at' => 'a','#text' => 'b'}]}}}, 'join => " " (1)' or diag dd($data),"\n"; } { local $X2H{join} = ' '; is_deeply $data = xml2hash($xml1), {root => {'-at' => 'key',nest => {'#text' => 'first mid last',vv => '',v => ['a',{'-at' => 'a','#text' => 'b'}]}}}, 'X2H.join = " " (1)' or diag dd($data),"\n"; } { is_deeply $data = xml2hash(q{}, comm => '#comment'), {root => {'#comment' => 'test'}}, 'comment node' or diag dd($data),"\n"; } { is_deeply $data = xml2hash(q{test}, text => '#textnode'), {root => { -x => 1, '#textnode' => 'test' }}, 'text node' or diag dd($data),"\n"; } { is_deeply $data = xml2hash(q{}, cdata => '#cdata'), {root => { -x => 1, '#cdata' => 'test' }}, 'cdata node' or diag dd($data),"\n"; } # Composing # Due to unpredictable order of hash keys # { node => { a => 1, b => 2 } } # could be one of: # 12 # 21 # So, in tests used more complex form with predictable order: # { node => [ { a => 1 }, { b => 2 } ] } # which produce always # 12 our $xml = qq{\n}; { is $data = hash2xml( { node => [ { -attr => "test" }, { sub => 'test' }, { tx => { '#text' => ' zzzz ' } } ] } ), qq{$xmltestzzzz\n}, 'default 1', ; } { is $data = hash2xml( { node => [ { _attr => "test" }, { sub => 'test' }, { tx => { '#text' => 'zzzz' } } ] }, attr => '_' ), qq{$xmltestzzzz\n}, 'attr _', ; } { is $data = hash2xml( { node => [ { -attr => "test" }, { sub => 'test' }, { tx => { '~' => 'zzzz' } } ] }, text => '~' ), qq{$xmltestzzzz\n}, 'text ~', ; } { is $data = hash2xml( { node => { sub => [ " \t\n", 'test' ] } }, trim => 1 ), qq{$xmltest\n}, 'trim 0', ; is $data = hash2xml( { node => { sub => [ " \t\n", 'test' ] } }, trim => 0 ), qq{$xml \t\ntest\n}, 'trim 1', ; } { is $data = hash2xml( { node => { sub => { '@' => 'test' } } }, cdata => '@' ), qq{$xml\n}, 'cdata @', ; } { is $data = hash2xml( { node => { sub => { '/' => 'test' } } },comm => '/' ), qq{$xml\n}, 'comm /', ; } { is $data = hash2xml( { node => { -attr => undef, '#cdata' => undef, '/' => undef, x=>undef } }, cdata => '#cdata', comm => '/' ), qq{$xml\n}, 'empty attr', ; } { is $data = hash2xml( { node => { test => "Тест" } }, encoding => 'cp1251' ), qq{\n\322\345\361\362\n}, 'encoding support', ; } XML-Hash-LX-0.0603/ex/profile.pl000644 002100 002100 00000000406 11623166253 016030 0ustar00monsmons000000 000000 #!/usr/bin/env perl use strict; use lib::abs '../lib'; use XML::Hash::LX; $ENV{NYTPROF} = 'trace=2:start=no:file='.lib::abs::path('.').'/nytprof.out'; my $xml = do 'xml.pl'; my $hash = xml2hash($xml); DB::enable_profile(); for (1..100) { hash2xml($hash); } XML-Hash-LX-0.0603/ex/test.pl000644 002100 002100 00000003621 11623166253 015351 0ustar00monsmons000000 000000 #!/usr/bin/env perl use strict; use lib::abs '../lib'; #BEGIN{ $XML::LibXML::Hash::X2H{trim} = 0; } use XML::Hash::LX; use Data::Dumper; $Data::Dumper::Indent = 1; $Data::Dumper::Useqq = 1; # xml to hash options $XML::Hash::LX::X2H{trim} = 0; # don't trim whitespace $XML::Hash::LX::X2H{attr} = '+'; # make attributes as keys with prefix '+'; $XML::Hash::LX::X2H{text} = '~'; # make text node as key '~'; #$XML::Hash::LX::X2H{join} = ' '; # join all whitespaces with ' '; #$XML::Hash::LX::X2H{join} = undef;# don't join text nodes $XML::Hash::LX::X2H{cdata} = '#'; # separate cdata sections from common values and save it under key '#'; $XML::Hash::LX::X2H{comm} = '//'; # keep comments and store under key '//'; # array cast $XML::Hash::LX::X2A{nest} = 1; # node with name 'nest' should be always stored as array #$XML::Hash::LX::X2A = 1; # all nodes should be always stored as array #$XML::Hash::LX::X2H{order} = 1; # keep order strictly my $hash = xml2hash q{ first a mid b > content ]]> last }, attr => '.', # locally override attr to be prefixed with '.' ; print +Dumper $hash; # hash to xml options $XML::Hash::LX::H2X{trim} = 1; # ignore whitespace $XML::Hash::LX::H2X{attr} = '+'; # keys, starting from '+' are attributes $XML::Hash::LX::H2X{text} = '~'; # key '~' is text node $XML::Hash::LX::H2X{cdata} = '#'; # key '#' is CDATA node $XML::Hash::LX::H2X{comm} = '//'; # key '//' is comment node # scalarref is treated as raw xml $hash->{root}{inject} = \(''); # refref is treated as XML::LibXML elements, and will be cloned and inserted $hash->{root}{add} = \( XML::LibXML::Element->new('test') ); print hash2xml $hash, attr => '.', # locally override attr to be prefixed with '.' ; XML-Hash-LX-0.0603/ex/xpath.pl000644 002100 002100 00000000660 11623166253 015516 0ustar00monsmons000000 000000 #!/usr/bin/env perl use strict; use lib::abs '../lib'; use XML::LibXML; use XML::Hash::LX; use Data::Dumper; my $xml = do 'xml.pl'; # parse in common way my $doc = XML::LibXML->new->parse_string($xml); my $xp = XML::LibXML::XPathContext->new($doc); $xp->registerNs('rss', 'http://purl.org/rss/1.0/'); # then process xpath for ($xp->findnodes('//rss:item')) { # and convert to hash concrete nodes print Dumper+xml2hash($_); } XML-Hash-LX-0.0603/ex/benchmark.pl000644 002100 002100 00000001741 11623166253 016325 0ustar00monsmons000000 000000 #!/usr/bin/env perl use lib::abs '../lib'; use XML::Hash::LX; use XML::Hash; use XML::Simple; use XML::Twig; use XML::Bare; use Benchmark qw(:all); use Data::Dumper; my $xml_converter = XML::Hash->new(); #my $twig = XML::Twig->new(); my $xml = do 'xml.pl'; my $xh_hash = $xml_converter->fromXMLStringtoHash($xml); my $lx_hash = xml2hash($xml); my $xs_hash = XMLin($xml); =for rem cmpthese timethese 1000, { 'Bare' => sub { my $root = XML::Bare->new( text => $xml )->parse; }, 'Hash' => sub { my $xml_hash = $xml_converter->fromXMLStringtoHash($xml); }, 'Twig' => sub { XML::Twig->new()->parse($xml); }, 'Simple' => sub { my $xml_hash = XMLin($xml); }, 'Hash::LX' => sub { my $xml_hash = xml2hash($xml); }, }; =for rem =cut #=for rem cmpthese timethese 100, { 'Hash' => sub { my $oxml = $xml_converter->fromHashtoXMLString($xh_hash); }, 'Simple' => sub { my $oxml = XMLout($xs_hash); }, 'Hash::LX' => sub { my $oxml = hash2xml($lx_hash); }, }; =for rem =cut XML-Hash-LX-0.0603/ex/xml.pl000644 002100 002100 00000000514 11623166253 015170 0ustar00monsmons000000 000000 use LWP::Simple 'get'; use lib::abs; sub { my $fn = lib::abs::path('.').'/uploads.rdf'; open my $f, '<',$fn or return do { warn "Fetching file\n"; my $data = get 'http://search.cpan.org/uploads.rdf'; open my $fo, '>', $fn; print $fo $data; close $fo; $data; }; warn "Have preloaded file\n"; local $/; <$f> }->(); XML-Hash-LX-0.0603/inc/Module/000755 002100 002100 00000000000 11623443777 015426 5ustar00monsmons000000 000000 XML-Hash-LX-0.0603/inc/Module/Install.pm000644 002100 002100 00000030135 11623443757 017372 0ustar00monsmons000000 000000 #line 1 package Module::Install; # For any maintainers: # The load order for Module::Install is a bit magic. # It goes something like this... # # IF ( host has Module::Install installed, creating author mode ) { # 1. Makefile.PL calls "use inc::Module::Install" # 2. $INC{inc/Module/Install.pm} set to installed version of inc::Module::Install # 3. The installed version of inc::Module::Install loads # 4. inc::Module::Install calls "require Module::Install" # 5. The ./inc/ version of Module::Install loads # } ELSE { # 1. Makefile.PL calls "use inc::Module::Install" # 2. $INC{inc/Module/Install.pm} set to ./inc/ version of Module::Install # 3. The ./inc/ version of Module::Install loads # } use 5.005; use strict 'vars'; use Cwd (); use File::Find (); use File::Path (); use vars qw{$VERSION $MAIN}; BEGIN { # All Module::Install core packages now require synchronised versions. # This will be used to ensure we don't accidentally load old or # different versions of modules. # This is not enforced yet, but will be some time in the next few # releases once we can make sure it won't clash with custom # Module::Install extensions. $VERSION = '1.01'; # Storage for the pseudo-singleton $MAIN = undef; *inc::Module::Install::VERSION = *VERSION; @inc::Module::Install::ISA = __PACKAGE__; } sub import { my $class = shift; my $self = $class->new(@_); my $who = $self->_caller; #------------------------------------------------------------- # all of the following checks should be included in import(), # to allow "eval 'require Module::Install; 1' to test # installation of Module::Install. (RT #51267) #------------------------------------------------------------- # Whether or not inc::Module::Install is actually loaded, the # $INC{inc/Module/Install.pm} is what will still get set as long as # the caller loaded module this in the documented manner. # If not set, the caller may NOT have loaded the bundled version, and thus # they may not have a MI version that works with the Makefile.PL. This would # result in false errors or unexpected behaviour. And we don't want that. my $file = join( '/', 'inc', split /::/, __PACKAGE__ ) . '.pm'; unless ( $INC{$file} ) { die <<"END_DIE" } Please invoke ${\__PACKAGE__} with: use inc::${\__PACKAGE__}; not: use ${\__PACKAGE__}; END_DIE # This reportedly fixes a rare Win32 UTC file time issue, but # as this is a non-cross-platform XS module not in the core, # we shouldn't really depend on it. See RT #24194 for detail. # (Also, this module only supports Perl 5.6 and above). eval "use Win32::UTCFileTime" if $^O eq 'MSWin32' && $] >= 5.006; # If the script that is loading Module::Install is from the future, # then make will detect this and cause it to re-run over and over # again. This is bad. Rather than taking action to touch it (which # is unreliable on some platforms and requires write permissions) # for now we should catch this and refuse to run. if ( -f $0 ) { my $s = (stat($0))[9]; # If the modification time is only slightly in the future, # sleep briefly to remove the problem. my $a = $s - time; if ( $a > 0 and $a < 5 ) { sleep 5 } # Too far in the future, throw an error. my $t = time; if ( $s > $t ) { die <<"END_DIE" } Your installer $0 has a modification time in the future ($s > $t). This is known to create infinite loops in make. Please correct this, then run $0 again. END_DIE } # Build.PL was formerly supported, but no longer is due to excessive # difficulty in implementing every single feature twice. if ( $0 =~ /Build.PL$/i ) { die <<"END_DIE" } Module::Install no longer supports Build.PL. It was impossible to maintain duel backends, and has been deprecated. Please remove all Build.PL files and only use the Makefile.PL installer. END_DIE #------------------------------------------------------------- # To save some more typing in Module::Install installers, every... # use inc::Module::Install # ...also acts as an implicit use strict. $^H |= strict::bits(qw(refs subs vars)); #------------------------------------------------------------- unless ( -f $self->{file} ) { foreach my $key (keys %INC) { delete $INC{$key} if $key =~ /Module\/Install/; } local $^W; require "$self->{path}/$self->{dispatch}.pm"; File::Path::mkpath("$self->{prefix}/$self->{author}"); $self->{admin} = "$self->{name}::$self->{dispatch}"->new( _top => $self ); $self->{admin}->init; @_ = ($class, _self => $self); goto &{"$self->{name}::import"}; } local $^W; *{"${who}::AUTOLOAD"} = $self->autoload; $self->preload; # Unregister loader and worker packages so subdirs can use them again delete $INC{'inc/Module/Install.pm'}; delete $INC{'Module/Install.pm'}; # Save to the singleton $MAIN = $self; return 1; } sub autoload { my $self = shift; my $who = $self->_caller; my $cwd = Cwd::cwd(); my $sym = "${who}::AUTOLOAD"; $sym->{$cwd} = sub { my $pwd = Cwd::cwd(); if ( my $code = $sym->{$pwd} ) { # Delegate back to parent dirs goto &$code unless $cwd eq $pwd; } unless ($$sym =~ s/([^:]+)$//) { # XXX: it looks like we can't retrieve the missing function # via $$sym (usually $main::AUTOLOAD) in this case. # I'm still wondering if we should slurp Makefile.PL to # get some context or not ... my ($package, $file, $line) = caller; die <<"EOT"; Unknown function is found at $file line $line. Execution of $file aborted due to runtime errors. If you're a contributor to a project, you may need to install some Module::Install extensions from CPAN (or other repository). If you're a user of a module, please contact the author. EOT } my $method = $1; if ( uc($method) eq $method ) { # Do nothing return; } elsif ( $method =~ /^_/ and $self->can($method) ) { # Dispatch to the root M:I class return $self->$method(@_); } # Dispatch to the appropriate plugin unshift @_, ( $self, $1 ); goto &{$self->can('call')}; }; } sub preload { my $self = shift; unless ( $self->{extensions} ) { $self->load_extensions( "$self->{prefix}/$self->{path}", $self ); } my @exts = @{$self->{extensions}}; unless ( @exts ) { @exts = $self->{admin}->load_all_extensions; } my %seen; foreach my $obj ( @exts ) { while (my ($method, $glob) = each %{ref($obj) . '::'}) { next unless $obj->can($method); next if $method =~ /^_/; next if $method eq uc($method); $seen{$method}++; } } my $who = $self->_caller; foreach my $name ( sort keys %seen ) { local $^W; *{"${who}::$name"} = sub { ${"${who}::AUTOLOAD"} = "${who}::$name"; goto &{"${who}::AUTOLOAD"}; }; } } sub new { my ($class, %args) = @_; delete $INC{'FindBin.pm'}; { # to suppress the redefine warning local $SIG{__WARN__} = sub {}; require FindBin; } # ignore the prefix on extension modules built from top level. my $base_path = Cwd::abs_path($FindBin::Bin); unless ( Cwd::abs_path(Cwd::cwd()) eq $base_path ) { delete $args{prefix}; } return $args{_self} if $args{_self}; $args{dispatch} ||= 'Admin'; $args{prefix} ||= 'inc'; $args{author} ||= ($^O eq 'VMS' ? '_author' : '.author'); $args{bundle} ||= 'inc/BUNDLES'; $args{base} ||= $base_path; $class =~ s/^\Q$args{prefix}\E:://; $args{name} ||= $class; $args{version} ||= $class->VERSION; unless ( $args{path} ) { $args{path} = $args{name}; $args{path} =~ s!::!/!g; } $args{file} ||= "$args{base}/$args{prefix}/$args{path}.pm"; $args{wrote} = 0; bless( \%args, $class ); } sub call { my ($self, $method) = @_; my $obj = $self->load($method) or return; splice(@_, 0, 2, $obj); goto &{$obj->can($method)}; } sub load { my ($self, $method) = @_; $self->load_extensions( "$self->{prefix}/$self->{path}", $self ) unless $self->{extensions}; foreach my $obj (@{$self->{extensions}}) { return $obj if $obj->can($method); } my $admin = $self->{admin} or die <<"END_DIE"; The '$method' method does not exist in the '$self->{prefix}' path! Please remove the '$self->{prefix}' directory and run $0 again to load it. END_DIE my $obj = $admin->load($method, 1); push @{$self->{extensions}}, $obj; $obj; } sub load_extensions { my ($self, $path, $top) = @_; my $should_reload = 0; unless ( grep { ! ref $_ and lc $_ eq lc $self->{prefix} } @INC ) { unshift @INC, $self->{prefix}; $should_reload = 1; } foreach my $rv ( $self->find_extensions($path) ) { my ($file, $pkg) = @{$rv}; next if $self->{pathnames}{$pkg}; local $@; my $new = eval { local $^W; require $file; $pkg->can('new') }; unless ( $new ) { warn $@ if $@; next; } $self->{pathnames}{$pkg} = $should_reload ? delete $INC{$file} : $INC{$file}; push @{$self->{extensions}}, &{$new}($pkg, _top => $top ); } $self->{extensions} ||= []; } sub find_extensions { my ($self, $path) = @_; my @found; File::Find::find( sub { my $file = $File::Find::name; return unless $file =~ m!^\Q$path\E/(.+)\.pm\Z!is; my $subpath = $1; return if lc($subpath) eq lc($self->{dispatch}); $file = "$self->{path}/$subpath.pm"; my $pkg = "$self->{name}::$subpath"; $pkg =~ s!/!::!g; # If we have a mixed-case package name, assume case has been preserved # correctly. Otherwise, root through the file to locate the case-preserved # version of the package name. if ( $subpath eq lc($subpath) || $subpath eq uc($subpath) ) { my $content = Module::Install::_read($subpath . '.pm'); my $in_pod = 0; foreach ( split //, $content ) { $in_pod = 1 if /^=\w/; $in_pod = 0 if /^=cut/; next if ($in_pod || /^=cut/); # skip pod text next if /^\s*#/; # and comments if ( m/^\s*package\s+($pkg)\s*;/i ) { $pkg = $1; last; } } } push @found, [ $file, $pkg ]; }, $path ) if -d $path; @found; } ##################################################################### # Common Utility Functions sub _caller { my $depth = 0; my $call = caller($depth); while ( $call eq __PACKAGE__ ) { $depth++; $call = caller($depth); } return $call; } # Done in evals to avoid confusing Perl::MinimumVersion eval( $] >= 5.006 ? <<'END_NEW' : <<'END_OLD' ); die $@ if $@; sub _read { local *FH; open( FH, '<', $_[0] ) or die "open($_[0]): $!"; my $string = do { local $/; }; close FH or die "close($_[0]): $!"; return $string; } END_NEW sub _read { local *FH; open( FH, "< $_[0]" ) or die "open($_[0]): $!"; my $string = do { local $/; }; close FH or die "close($_[0]): $!"; return $string; } END_OLD sub _readperl { my $string = Module::Install::_read($_[0]); $string =~ s/(?:\015{1,2}\012|\015|\012)/\n/sg; $string =~ s/(\n)\n*__(?:DATA|END)__\b.*\z/$1/s; $string =~ s/\n\n=\w+.+?\n\n=cut\b.+?\n+/\n\n/sg; return $string; } sub _readpod { my $string = Module::Install::_read($_[0]); $string =~ s/(?:\015{1,2}\012|\015|\012)/\n/sg; return $string if $_[0] =~ /\.pod\z/; $string =~ s/(^|\n=cut\b.+?\n+)[^=\s].+?\n(\n=\w+|\z)/$1$2/sg; $string =~ s/\n*=pod\b[^\n]*\n+/\n\n/sg; $string =~ s/\n*=cut\b[^\n]*\n+/\n\n/sg; $string =~ s/^\n+//s; return $string; } # Done in evals to avoid confusing Perl::MinimumVersion eval( $] >= 5.006 ? <<'END_NEW' : <<'END_OLD' ); die $@ if $@; sub _write { local *FH; open( FH, '>', $_[0] ) or die "open($_[0]): $!"; foreach ( 1 .. $#_ ) { print FH $_[$_] or die "print($_[0]): $!"; } close FH or die "close($_[0]): $!"; } END_NEW sub _write { local *FH; open( FH, "> $_[0]" ) or die "open($_[0]): $!"; foreach ( 1 .. $#_ ) { print FH $_[$_] or die "print($_[0]): $!"; } close FH or die "close($_[0]): $!"; } END_OLD # _version is for processing module versions (eg, 1.03_05) not # Perl versions (eg, 5.8.1). sub _version ($) { my $s = shift || 0; my $d =()= $s =~ /(\.)/g; if ( $d >= 2 ) { # Normalise multipart versions $s =~ s/(\.)(\d{1,3})/sprintf("$1%03d",$2)/eg; } $s =~ s/^(\d+)\.?//; my $l = $1 || 0; my @v = map { $_ . '0' x (3 - length $_) } $s =~ /(\d{1,3})\D?/g; $l = $l . '.' . join '', @v if @v; return $l + 0; } sub _cmp ($$) { _version($_[0]) <=> _version($_[1]); } # Cloned from Params::Util::_CLASS sub _CLASS ($) { ( defined $_[0] and ! ref $_[0] and $_[0] =~ m/^[^\W\d]\w*(?:::\w+)*\z/s ) ? $_[0] : undef; } 1; # Copyright 2008 - 2011 Adam Kennedy. XML-Hash-LX-0.0603/inc/Module/Install/000755 002100 002100 00000000000 11623443777 017034 5ustar00monsmons000000 000000 XML-Hash-LX-0.0603/inc/Module/AutoInstall.pm000644 002100 002100 00000054231 11623443761 020221 0ustar00monsmons000000 000000 #line 1 package Module::AutoInstall; use strict; use Cwd (); use ExtUtils::MakeMaker (); use vars qw{$VERSION}; BEGIN { $VERSION = '1.03'; } # special map on pre-defined feature sets my %FeatureMap = ( '' => 'Core Features', # XXX: deprecated '-core' => 'Core Features', ); # various lexical flags my ( @Missing, @Existing, %DisabledTests, $UnderCPAN, $HasCPANPLUS ); my ( $Config, $CheckOnly, $SkipInstall, $AcceptDefault, $TestOnly, $AllDeps ); my ( $PostambleActions, $PostambleUsed ); # See if it's a testing or non-interactive session _accept_default( $ENV{AUTOMATED_TESTING} or ! -t STDIN ); _init(); sub _accept_default { $AcceptDefault = shift; } sub missing_modules { return @Missing; } sub do_install { __PACKAGE__->install( [ $Config ? ( UNIVERSAL::isa( $Config, 'HASH' ) ? %{$Config} : @{$Config} ) : () ], @Missing, ); } # initialize various flags, and/or perform install sub _init { foreach my $arg ( @ARGV, split( /[\s\t]+/, $ENV{PERL_AUTOINSTALL} || $ENV{PERL_EXTUTILS_AUTOINSTALL} || '' ) ) { if ( $arg =~ /^--config=(.*)$/ ) { $Config = [ split( ',', $1 ) ]; } elsif ( $arg =~ /^--installdeps=(.*)$/ ) { __PACKAGE__->install( $Config, @Missing = split( /,/, $1 ) ); exit 0; } elsif ( $arg =~ /^--default(?:deps)?$/ ) { $AcceptDefault = 1; } elsif ( $arg =~ /^--check(?:deps)?$/ ) { $CheckOnly = 1; } elsif ( $arg =~ /^--skip(?:deps)?$/ ) { $SkipInstall = 1; } elsif ( $arg =~ /^--test(?:only)?$/ ) { $TestOnly = 1; } elsif ( $arg =~ /^--all(?:deps)?$/ ) { $AllDeps = 1; } } } # overrides MakeMaker's prompt() to automatically accept the default choice sub _prompt { goto &ExtUtils::MakeMaker::prompt unless $AcceptDefault; my ( $prompt, $default ) = @_; my $y = ( $default =~ /^[Yy]/ ); print $prompt, ' [', ( $y ? 'Y' : 'y' ), '/', ( $y ? 'n' : 'N' ), '] '; print "$default\n"; return $default; } # the workhorse sub import { my $class = shift; my @args = @_ or return; my $core_all; print "*** $class version " . $class->VERSION . "\n"; print "*** Checking for Perl dependencies...\n"; my $cwd = Cwd::cwd(); $Config = []; my $maxlen = length( ( sort { length($b) <=> length($a) } grep { /^[^\-]/ } map { ref($_) ? ( ( ref($_) eq 'HASH' ) ? keys(%$_) : @{$_} ) : '' } map { +{@args}->{$_} } grep { /^[^\-]/ or /^-core$/i } keys %{ +{@args} } )[0] ); # We want to know if we're under CPAN early to avoid prompting, but # if we aren't going to try and install anything anyway then skip the # check entirely since we don't want to have to load (and configure) # an old CPAN just for a cosmetic message $UnderCPAN = _check_lock(1) unless $SkipInstall; while ( my ( $feature, $modules ) = splice( @args, 0, 2 ) ) { my ( @required, @tests, @skiptests ); my $default = 1; my $conflict = 0; if ( $feature =~ m/^-(\w+)$/ ) { my $option = lc($1); # check for a newer version of myself _update_to( $modules, @_ ) and return if $option eq 'version'; # sets CPAN configuration options $Config = $modules if $option eq 'config'; # promote every features to core status $core_all = ( $modules =~ /^all$/i ) and next if $option eq 'core'; next unless $option eq 'core'; } print "[" . ( $FeatureMap{ lc($feature) } || $feature ) . "]\n"; $modules = [ %{$modules} ] if UNIVERSAL::isa( $modules, 'HASH' ); unshift @$modules, -default => &{ shift(@$modules) } if ( ref( $modules->[0] ) eq 'CODE' ); # XXX: bugward combatability while ( my ( $mod, $arg ) = splice( @$modules, 0, 2 ) ) { if ( $mod =~ m/^-(\w+)$/ ) { my $option = lc($1); $default = $arg if ( $option eq 'default' ); $conflict = $arg if ( $option eq 'conflict' ); @tests = @{$arg} if ( $option eq 'tests' ); @skiptests = @{$arg} if ( $option eq 'skiptests' ); next; } printf( "- %-${maxlen}s ...", $mod ); if ( $arg and $arg =~ /^\D/ ) { unshift @$modules, $arg; $arg = 0; } # XXX: check for conflicts and uninstalls(!) them. my $cur = _load($mod); if (_version_cmp ($cur, $arg) >= 0) { print "loaded. ($cur" . ( $arg ? " >= $arg" : '' ) . ")\n"; push @Existing, $mod => $arg; $DisabledTests{$_} = 1 for map { glob($_) } @skiptests; } else { if (not defined $cur) # indeed missing { print "missing." . ( $arg ? " (would need $arg)" : '' ) . "\n"; } else { # no need to check $arg as _version_cmp ($cur, undef) would satisfy >= above print "too old. ($cur < $arg)\n"; } push @required, $mod => $arg; } } next unless @required; my $mandatory = ( $feature eq '-core' or $core_all ); if ( !$SkipInstall and ( $CheckOnly or ($mandatory and $UnderCPAN) or $AllDeps or _prompt( qq{==> Auto-install the } . ( @required / 2 ) . ( $mandatory ? ' mandatory' : ' optional' ) . qq{ module(s) from CPAN?}, $default ? 'y' : 'n', ) =~ /^[Yy]/ ) ) { push( @Missing, @required ); $DisabledTests{$_} = 1 for map { glob($_) } @skiptests; } elsif ( !$SkipInstall and $default and $mandatory and _prompt( qq{==> The module(s) are mandatory! Really skip?}, 'n', ) =~ /^[Nn]/ ) { push( @Missing, @required ); $DisabledTests{$_} = 1 for map { glob($_) } @skiptests; } else { $DisabledTests{$_} = 1 for map { glob($_) } @tests; } } if ( @Missing and not( $CheckOnly or $UnderCPAN ) ) { require Config; print "*** Dependencies will be installed the next time you type '$Config::Config{make}'.\n"; # make an educated guess of whether we'll need root permission. print " (You may need to do that as the 'root' user.)\n" if eval '$>'; } print "*** $class configuration finished.\n"; chdir $cwd; # import to main:: no strict 'refs'; *{'main::WriteMakefile'} = \&Write if caller(0) eq 'main'; return (@Existing, @Missing); } sub _running_under { my $thing = shift; print <<"END_MESSAGE"; *** Since we're running under ${thing}, I'll just let it take care of the dependency's installation later. END_MESSAGE return 1; } # Check to see if we are currently running under CPAN.pm and/or CPANPLUS; # if we are, then we simply let it taking care of our dependencies sub _check_lock { return unless @Missing or @_; my $cpan_env = $ENV{PERL5_CPAN_IS_RUNNING}; if ($ENV{PERL5_CPANPLUS_IS_RUNNING}) { return _running_under($cpan_env ? 'CPAN' : 'CPANPLUS'); } require CPAN; if ($CPAN::VERSION > '1.89') { if ($cpan_env) { return _running_under('CPAN'); } return; # CPAN.pm new enough, don't need to check further } # last ditch attempt, this -will- configure CPAN, very sorry _load_cpan(1); # force initialize even though it's already loaded # Find the CPAN lock-file my $lock = MM->catfile( $CPAN::Config->{cpan_home}, ".lock" ); return unless -f $lock; # Check the lock local *LOCK; return unless open(LOCK, $lock); if ( ( $^O eq 'MSWin32' ? _under_cpan() : == getppid() ) and ( $CPAN::Config->{prerequisites_policy} || '' ) ne 'ignore' ) { print <<'END_MESSAGE'; *** Since we're running under CPAN, I'll just let it take care of the dependency's installation later. END_MESSAGE return 1; } close LOCK; return; } sub install { my $class = shift; my $i; # used below to strip leading '-' from config keys my @config = ( map { s/^-// if ++$i; $_ } @{ +shift } ); my ( @modules, @installed ); while ( my ( $pkg, $ver ) = splice( @_, 0, 2 ) ) { # grep out those already installed if ( _version_cmp( _load($pkg), $ver ) >= 0 ) { push @installed, $pkg; } else { push @modules, $pkg, $ver; } } return @installed unless @modules; # nothing to do return @installed if _check_lock(); # defer to the CPAN shell print "*** Installing dependencies...\n"; return unless _connected_to('cpan.org'); my %args = @config; my %failed; local *FAILED; if ( $args{do_once} and open( FAILED, '.#autoinstall.failed' ) ) { while () { chomp; $failed{$_}++ } close FAILED; my @newmod; while ( my ( $k, $v ) = splice( @modules, 0, 2 ) ) { push @newmod, ( $k => $v ) unless $failed{$k}; } @modules = @newmod; } if ( _has_cpanplus() and not $ENV{PERL_AUTOINSTALL_PREFER_CPAN} ) { _install_cpanplus( \@modules, \@config ); } else { _install_cpan( \@modules, \@config ); } print "*** $class installation finished.\n"; # see if we have successfully installed them while ( my ( $pkg, $ver ) = splice( @modules, 0, 2 ) ) { if ( _version_cmp( _load($pkg), $ver ) >= 0 ) { push @installed, $pkg; } elsif ( $args{do_once} and open( FAILED, '>> .#autoinstall.failed' ) ) { print FAILED "$pkg\n"; } } close FAILED if $args{do_once}; return @installed; } sub _install_cpanplus { my @modules = @{ +shift }; my @config = _cpanplus_config( @{ +shift } ); my $installed = 0; require CPANPLUS::Backend; my $cp = CPANPLUS::Backend->new; my $conf = $cp->configure_object; return unless $conf->can('conf') # 0.05x+ with "sudo" support or _can_write($conf->_get_build('base')); # 0.04x # if we're root, set UNINST=1 to avoid trouble unless user asked for it. my $makeflags = $conf->get_conf('makeflags') || ''; if ( UNIVERSAL::isa( $makeflags, 'HASH' ) ) { # 0.03+ uses a hashref here $makeflags->{UNINST} = 1 unless exists $makeflags->{UNINST}; } else { # 0.02 and below uses a scalar $makeflags = join( ' ', split( ' ', $makeflags ), 'UNINST=1' ) if ( $makeflags !~ /\bUNINST\b/ and eval qq{ $> eq '0' } ); } $conf->set_conf( makeflags => $makeflags ); $conf->set_conf( prereqs => 1 ); while ( my ( $key, $val ) = splice( @config, 0, 2 ) ) { $conf->set_conf( $key, $val ); } my $modtree = $cp->module_tree; while ( my ( $pkg, $ver ) = splice( @modules, 0, 2 ) ) { print "*** Installing $pkg...\n"; MY::preinstall( $pkg, $ver ) or next if defined &MY::preinstall; my $success; my $obj = $modtree->{$pkg}; if ( $obj and _version_cmp( $obj->{version}, $ver ) >= 0 ) { my $pathname = $pkg; $pathname =~ s/::/\\W/; foreach my $inc ( grep { m/$pathname.pm/i } keys(%INC) ) { delete $INC{$inc}; } my $rv = $cp->install( modules => [ $obj->{module} ] ); if ( $rv and ( $rv->{ $obj->{module} } or $rv->{ok} ) ) { print "*** $pkg successfully installed.\n"; $success = 1; } else { print "*** $pkg installation cancelled.\n"; $success = 0; } $installed += $success; } else { print << "."; *** Could not find a version $ver or above for $pkg; skipping. . } MY::postinstall( $pkg, $ver, $success ) if defined &MY::postinstall; } return $installed; } sub _cpanplus_config { my @config = (); while ( @_ ) { my ($key, $value) = (shift(), shift()); if ( $key eq 'prerequisites_policy' ) { if ( $value eq 'follow' ) { $value = CPANPLUS::Internals::Constants::PREREQ_INSTALL(); } elsif ( $value eq 'ask' ) { $value = CPANPLUS::Internals::Constants::PREREQ_ASK(); } elsif ( $value eq 'ignore' ) { $value = CPANPLUS::Internals::Constants::PREREQ_IGNORE(); } else { die "*** Cannot convert option $key = '$value' to CPANPLUS version.\n"; } } else { die "*** Cannot convert option $key to CPANPLUS version.\n"; } } return @config; } sub _install_cpan { my @modules = @{ +shift }; my @config = @{ +shift }; my $installed = 0; my %args; _load_cpan(); require Config; if (CPAN->VERSION < 1.80) { # no "sudo" support, probe for writableness return unless _can_write( MM->catfile( $CPAN::Config->{cpan_home}, 'sources' ) ) and _can_write( $Config::Config{sitelib} ); } # if we're root, set UNINST=1 to avoid trouble unless user asked for it. my $makeflags = $CPAN::Config->{make_install_arg} || ''; $CPAN::Config->{make_install_arg} = join( ' ', split( ' ', $makeflags ), 'UNINST=1' ) if ( $makeflags !~ /\bUNINST\b/ and eval qq{ $> eq '0' } ); # don't show start-up info $CPAN::Config->{inhibit_startup_message} = 1; # set additional options while ( my ( $opt, $arg ) = splice( @config, 0, 2 ) ) { ( $args{$opt} = $arg, next ) if $opt =~ /^force$/; # pseudo-option $CPAN::Config->{$opt} = $arg; } local $CPAN::Config->{prerequisites_policy} = 'follow'; while ( my ( $pkg, $ver ) = splice( @modules, 0, 2 ) ) { MY::preinstall( $pkg, $ver ) or next if defined &MY::preinstall; print "*** Installing $pkg...\n"; my $obj = CPAN::Shell->expand( Module => $pkg ); my $success = 0; if ( $obj and _version_cmp( $obj->cpan_version, $ver ) >= 0 ) { my $pathname = $pkg; $pathname =~ s/::/\\W/; foreach my $inc ( grep { m/$pathname.pm/i } keys(%INC) ) { delete $INC{$inc}; } my $rv = $args{force} ? CPAN::Shell->force( install => $pkg ) : CPAN::Shell->install($pkg); $rv ||= eval { $CPAN::META->instance( 'CPAN::Distribution', $obj->cpan_file, ) ->{install} if $CPAN::META; }; if ( $rv eq 'YES' ) { print "*** $pkg successfully installed.\n"; $success = 1; } else { print "*** $pkg installation failed.\n"; $success = 0; } $installed += $success; } else { print << "."; *** Could not find a version $ver or above for $pkg; skipping. . } MY::postinstall( $pkg, $ver, $success ) if defined &MY::postinstall; } return $installed; } sub _has_cpanplus { return ( $HasCPANPLUS = ( $INC{'CPANPLUS/Config.pm'} or _load('CPANPLUS::Shell::Default') ) ); } # make guesses on whether we're under the CPAN installation directory sub _under_cpan { require Cwd; require File::Spec; my $cwd = File::Spec->canonpath( Cwd::cwd() ); my $cpan = File::Spec->canonpath( $CPAN::Config->{cpan_home} ); return ( index( $cwd, $cpan ) > -1 ); } sub _update_to { my $class = __PACKAGE__; my $ver = shift; return if _version_cmp( _load($class), $ver ) >= 0; # no need to upgrade if ( _prompt( "==> A newer version of $class ($ver) is required. Install?", 'y' ) =~ /^[Nn]/ ) { die "*** Please install $class $ver manually.\n"; } print << "."; *** Trying to fetch it from CPAN... . # install ourselves _load($class) and return $class->import(@_) if $class->install( [], $class, $ver ); print << '.'; exit 1; *** Cannot bootstrap myself. :-( Installation terminated. . } # check if we're connected to some host, using inet_aton sub _connected_to { my $site = shift; return ( ( _load('Socket') and Socket::inet_aton($site) ) or _prompt( qq( *** Your host cannot resolve the domain name '$site', which probably means the Internet connections are unavailable. ==> Should we try to install the required module(s) anyway?), 'n' ) =~ /^[Yy]/ ); } # check if a directory is writable; may create it on demand sub _can_write { my $path = shift; mkdir( $path, 0755 ) unless -e $path; return 1 if -w $path; print << "."; *** You are not allowed to write to the directory '$path'; the installation may fail due to insufficient permissions. . if ( eval '$>' and lc(`sudo -V`) =~ /version/ and _prompt( qq( ==> Should we try to re-execute the autoinstall process with 'sudo'?), ((-t STDIN) ? 'y' : 'n') ) =~ /^[Yy]/ ) { # try to bootstrap ourselves from sudo print << "."; *** Trying to re-execute the autoinstall process with 'sudo'... . my $missing = join( ',', @Missing ); my $config = join( ',', UNIVERSAL::isa( $Config, 'HASH' ) ? %{$Config} : @{$Config} ) if $Config; return unless system( 'sudo', $^X, $0, "--config=$config", "--installdeps=$missing" ); print << "."; *** The 'sudo' command exited with error! Resuming... . } return _prompt( qq( ==> Should we try to install the required module(s) anyway?), 'n' ) =~ /^[Yy]/; } # load a module and return the version it reports sub _load { my $mod = pop; # class/instance doesn't matter my $file = $mod; $file =~ s|::|/|g; $file .= '.pm'; local $@; return eval { require $file; $mod->VERSION } || ( $@ ? undef: 0 ); } # Load CPAN.pm and it's configuration sub _load_cpan { return if $CPAN::VERSION and $CPAN::Config and not @_; require CPAN; # CPAN-1.82+ adds CPAN::Config::AUTOLOAD to redirect to # CPAN::HandleConfig->load. CPAN reports that the redirection # is deprecated in a warning printed at the user. # CPAN-1.81 expects CPAN::HandleConfig->load, does not have # $CPAN::HandleConfig::VERSION but cannot handle # CPAN::Config->load # Which "versions expect CPAN::Config->load? if ( $CPAN::HandleConfig::VERSION || CPAN::HandleConfig->can('load') ) { # Newer versions of CPAN have a HandleConfig module CPAN::HandleConfig->load; } else { # Older versions had the load method in Config directly CPAN::Config->load; } } # compare two versions, either use Sort::Versions or plain comparison # return values same as <=> sub _version_cmp { my ( $cur, $min ) = @_; return -1 unless defined $cur; # if 0 keep comparing return 1 unless $min; $cur =~ s/\s+$//; # check for version numbers that are not in decimal format if ( ref($cur) or ref($min) or $cur =~ /v|\..*\./ or $min =~ /v|\..*\./ ) { if ( ( $version::VERSION or defined( _load('version') )) and version->can('new') ) { # use version.pm if it is installed. return version->new($cur) <=> version->new($min); } elsif ( $Sort::Versions::VERSION or defined( _load('Sort::Versions') ) ) { # use Sort::Versions as the sorting algorithm for a.b.c versions return Sort::Versions::versioncmp( $cur, $min ); } warn "Cannot reliably compare non-decimal formatted versions.\n" . "Please install version.pm or Sort::Versions.\n"; } # plain comparison local $^W = 0; # shuts off 'not numeric' bugs return $cur <=> $min; } # nothing; this usage is deprecated. sub main::PREREQ_PM { return {}; } sub _make_args { my %args = @_; $args{PREREQ_PM} = { %{ $args{PREREQ_PM} || {} }, @Existing, @Missing } if $UnderCPAN or $TestOnly; if ( $args{EXE_FILES} and -e 'MANIFEST' ) { require ExtUtils::Manifest; my $manifest = ExtUtils::Manifest::maniread('MANIFEST'); $args{EXE_FILES} = [ grep { exists $manifest->{$_} } @{ $args{EXE_FILES} } ]; } $args{test}{TESTS} ||= 't/*.t'; $args{test}{TESTS} = join( ' ', grep { !exists( $DisabledTests{$_} ) } map { glob($_) } split( /\s+/, $args{test}{TESTS} ) ); my $missing = join( ',', @Missing ); my $config = join( ',', UNIVERSAL::isa( $Config, 'HASH' ) ? %{$Config} : @{$Config} ) if $Config; $PostambleActions = ( ($missing and not $UnderCPAN) ? "\$(PERL) $0 --config=$config --installdeps=$missing" : "\$(NOECHO) \$(NOOP)" ); return %args; } # a wrapper to ExtUtils::MakeMaker::WriteMakefile sub Write { require Carp; Carp::croak "WriteMakefile: Need even number of args" if @_ % 2; if ($CheckOnly) { print << "."; *** Makefile not written in check-only mode. . return; } my %args = _make_args(@_); no strict 'refs'; $PostambleUsed = 0; local *MY::postamble = \&postamble unless defined &MY::postamble; ExtUtils::MakeMaker::WriteMakefile(%args); print << "." unless $PostambleUsed; *** WARNING: Makefile written with customized MY::postamble() without including contents from Module::AutoInstall::postamble() -- auto installation features disabled. Please contact the author. . return 1; } sub postamble { $PostambleUsed = 1; return <<"END_MAKE"; config :: installdeps \t\$(NOECHO) \$(NOOP) checkdeps :: \t\$(PERL) $0 --checkdeps installdeps :: \t$PostambleActions END_MAKE } 1; __END__ #line 1071 XML-Hash-LX-0.0603/inc/Module/Install/AutoInstall.pm000644 002100 002100 00000003632 11623443761 021626 0ustar00monsmons000000 000000 #line 1 package Module::Install::AutoInstall; use strict; use Module::Install::Base (); use vars qw{$VERSION @ISA $ISCORE}; BEGIN { $VERSION = '1.01'; @ISA = 'Module::Install::Base'; $ISCORE = 1; } sub AutoInstall { $_[0] } sub run { my $self = shift; $self->auto_install_now(@_); } sub write { my $self = shift; $self->auto_install(@_); } sub auto_install { my $self = shift; return if $self->{done}++; # Flatten array of arrays into a single array my @core = map @$_, map @$_, grep ref, $self->build_requires, $self->requires; my @config = @_; # We'll need Module::AutoInstall $self->include('Module::AutoInstall'); require Module::AutoInstall; my @features_require = Module::AutoInstall->import( (@config ? (-config => \@config) : ()), (@core ? (-core => \@core) : ()), $self->features, ); my %seen; my @requires = map @$_, map @$_, grep ref, $self->requires; while (my ($mod, $ver) = splice(@requires, 0, 2)) { $seen{$mod}{$ver}++; } my @build_requires = map @$_, map @$_, grep ref, $self->build_requires; while (my ($mod, $ver) = splice(@build_requires, 0, 2)) { $seen{$mod}{$ver}++; } my @configure_requires = map @$_, map @$_, grep ref, $self->configure_requires; while (my ($mod, $ver) = splice(@configure_requires, 0, 2)) { $seen{$mod}{$ver}++; } my @deduped; while (my ($mod, $ver) = splice(@features_require, 0, 2)) { push @deduped, $mod => $ver unless $seen{$mod}{$ver}++; } $self->requires(@deduped); $self->makemaker_args( Module::AutoInstall::_make_args() ); my $class = ref($self); $self->postamble( "# --- $class section:\n" . Module::AutoInstall::postamble() ); } sub auto_install_now { my $self = shift; $self->auto_install(@_); Module::AutoInstall::do_install(); } 1; XML-Hash-LX-0.0603/inc/Module/Install/Makefile.pm000644 002100 002100 00000027032 11623443761 021104 0ustar00monsmons000000 000000 #line 1 package Module::Install::Makefile; use strict 'vars'; use ExtUtils::MakeMaker (); use Module::Install::Base (); use Fcntl qw/:flock :seek/; use vars qw{$VERSION @ISA $ISCORE}; BEGIN { $VERSION = '1.01'; @ISA = 'Module::Install::Base'; $ISCORE = 1; } sub Makefile { $_[0] } my %seen = (); sub prompt { shift; # Infinite loop protection my @c = caller(); if ( ++$seen{"$c[1]|$c[2]|$_[0]"} > 3 ) { die "Caught an potential prompt infinite loop ($c[1]|$c[2]|$_[0])"; } # In automated testing or non-interactive session, always use defaults if ( ($ENV{AUTOMATED_TESTING} or -! -t STDIN) and ! $ENV{PERL_MM_USE_DEFAULT} ) { local $ENV{PERL_MM_USE_DEFAULT} = 1; goto &ExtUtils::MakeMaker::prompt; } else { goto &ExtUtils::MakeMaker::prompt; } } # Store a cleaned up version of the MakeMaker version, # since we need to behave differently in a variety of # ways based on the MM version. my $makemaker = eval $ExtUtils::MakeMaker::VERSION; # If we are passed a param, do a "newer than" comparison. # Otherwise, just return the MakeMaker version. sub makemaker { ( @_ < 2 or $makemaker >= eval($_[1]) ) ? $makemaker : 0 } # Ripped from ExtUtils::MakeMaker 6.56, and slightly modified # as we only need to know here whether the attribute is an array # or a hash or something else (which may or may not be appendable). my %makemaker_argtype = ( C => 'ARRAY', CONFIG => 'ARRAY', # CONFIGURE => 'CODE', # ignore DIR => 'ARRAY', DL_FUNCS => 'HASH', DL_VARS => 'ARRAY', EXCLUDE_EXT => 'ARRAY', EXE_FILES => 'ARRAY', FUNCLIST => 'ARRAY', H => 'ARRAY', IMPORTS => 'HASH', INCLUDE_EXT => 'ARRAY', LIBS => 'ARRAY', # ignore '' MAN1PODS => 'HASH', MAN3PODS => 'HASH', META_ADD => 'HASH', META_MERGE => 'HASH', PL_FILES => 'HASH', PM => 'HASH', PMLIBDIRS => 'ARRAY', PMLIBPARENTDIRS => 'ARRAY', PREREQ_PM => 'HASH', CONFIGURE_REQUIRES => 'HASH', SKIP => 'ARRAY', TYPEMAPS => 'ARRAY', XS => 'HASH', # VERSION => ['version',''], # ignore # _KEEP_AFTER_FLUSH => '', clean => 'HASH', depend => 'HASH', dist => 'HASH', dynamic_lib=> 'HASH', linkext => 'HASH', macro => 'HASH', postamble => 'HASH', realclean => 'HASH', test => 'HASH', tool_autosplit => 'HASH', # special cases where you can use makemaker_append CCFLAGS => 'APPENDABLE', DEFINE => 'APPENDABLE', INC => 'APPENDABLE', LDDLFLAGS => 'APPENDABLE', LDFROM => 'APPENDABLE', ); sub makemaker_args { my ($self, %new_args) = @_; my $args = ( $self->{makemaker_args} ||= {} ); foreach my $key (keys %new_args) { if ($makemaker_argtype{$key}) { if ($makemaker_argtype{$key} eq 'ARRAY') { $args->{$key} = [] unless defined $args->{$key}; unless (ref $args->{$key} eq 'ARRAY') { $args->{$key} = [$args->{$key}] } push @{$args->{$key}}, ref $new_args{$key} eq 'ARRAY' ? @{$new_args{$key}} : $new_args{$key}; } elsif ($makemaker_argtype{$key} eq 'HASH') { $args->{$key} = {} unless defined $args->{$key}; foreach my $skey (keys %{ $new_args{$key} }) { $args->{$key}{$skey} = $new_args{$key}{$skey}; } } elsif ($makemaker_argtype{$key} eq 'APPENDABLE') { $self->makemaker_append($key => $new_args{$key}); } } else { if (defined $args->{$key}) { warn qq{MakeMaker attribute "$key" is overriden; use "makemaker_append" to append values\n}; } $args->{$key} = $new_args{$key}; } } return $args; } # For mm args that take multiple space-seperated args, # append an argument to the current list. sub makemaker_append { my $self = shift; my $name = shift; my $args = $self->makemaker_args; $args->{$name} = defined $args->{$name} ? join( ' ', $args->{$name}, @_ ) : join( ' ', @_ ); } sub build_subdirs { my $self = shift; my $subdirs = $self->makemaker_args->{DIR} ||= []; for my $subdir (@_) { push @$subdirs, $subdir; } } sub clean_files { my $self = shift; my $clean = $self->makemaker_args->{clean} ||= {}; %$clean = ( %$clean, FILES => join ' ', grep { length $_ } ($clean->{FILES} || (), @_), ); } sub realclean_files { my $self = shift; my $realclean = $self->makemaker_args->{realclean} ||= {}; %$realclean = ( %$realclean, FILES => join ' ', grep { length $_ } ($realclean->{FILES} || (), @_), ); } sub libs { my $self = shift; my $libs = ref $_[0] ? shift : [ shift ]; $self->makemaker_args( LIBS => $libs ); } sub inc { my $self = shift; $self->makemaker_args( INC => shift ); } sub _wanted_t { } sub tests_recursive { my $self = shift; my $dir = shift || 't'; unless ( -d $dir ) { die "tests_recursive dir '$dir' does not exist"; } my %tests = map { $_ => 1 } split / /, ($self->tests || ''); require File::Find; File::Find::find( sub { /\.t$/ and -f $_ and $tests{"$File::Find::dir/*.t"} = 1 }, $dir ); $self->tests( join ' ', sort keys %tests ); } sub write { my $self = shift; die "&Makefile->write() takes no arguments\n" if @_; # Check the current Perl version my $perl_version = $self->perl_version; if ( $perl_version ) { eval "use $perl_version; 1" or die "ERROR: perl: Version $] is installed, " . "but we need version >= $perl_version"; } # Make sure we have a new enough MakeMaker require ExtUtils::MakeMaker; if ( $perl_version and $self->_cmp($perl_version, '5.006') >= 0 ) { # MakeMaker can complain about module versions that include # an underscore, even though its own version may contain one! # Hence the funny regexp to get rid of it. See RT #35800 # for details. my $v = $ExtUtils::MakeMaker::VERSION =~ /^(\d+\.\d+)/; $self->build_requires( 'ExtUtils::MakeMaker' => $v ); $self->configure_requires( 'ExtUtils::MakeMaker' => $v ); } else { # Allow legacy-compatibility with 5.005 by depending on the # most recent EU:MM that supported 5.005. $self->build_requires( 'ExtUtils::MakeMaker' => 6.42 ); $self->configure_requires( 'ExtUtils::MakeMaker' => 6.42 ); } # Generate the MakeMaker params my $args = $self->makemaker_args; $args->{DISTNAME} = $self->name; $args->{NAME} = $self->module_name || $self->name; $args->{NAME} =~ s/-/::/g; $args->{VERSION} = $self->version or die <<'EOT'; ERROR: Can't determine distribution version. Please specify it explicitly via 'version' in Makefile.PL, or set a valid $VERSION in a module, and provide its file path via 'version_from' (or 'all_from' if you prefer) in Makefile.PL. EOT $DB::single = 1; if ( $self->tests ) { my @tests = split ' ', $self->tests; my %seen; $args->{test} = { TESTS => (join ' ', grep {!$seen{$_}++} @tests), }; } elsif ( $Module::Install::ExtraTests::use_extratests ) { # Module::Install::ExtraTests doesn't set $self->tests and does its own tests via harness. # So, just ignore our xt tests here. } elsif ( -d 'xt' and ($Module::Install::AUTHOR or $ENV{RELEASE_TESTING}) ) { $args->{test} = { TESTS => join( ' ', map { "$_/*.t" } grep { -d $_ } qw{ t xt } ), }; } if ( $] >= 5.005 ) { $args->{ABSTRACT} = $self->abstract; $args->{AUTHOR} = join ', ', @{$self->author || []}; } if ( $self->makemaker(6.10) ) { $args->{NO_META} = 1; #$args->{NO_MYMETA} = 1; } if ( $self->makemaker(6.17) and $self->sign ) { $args->{SIGN} = 1; } unless ( $self->is_admin ) { delete $args->{SIGN}; } if ( $self->makemaker(6.31) and $self->license ) { $args->{LICENSE} = $self->license; } my $prereq = ($args->{PREREQ_PM} ||= {}); %$prereq = ( %$prereq, map { @$_ } # flatten [module => version] map { @$_ } grep $_, ($self->requires) ); # Remove any reference to perl, PREREQ_PM doesn't support it delete $args->{PREREQ_PM}->{perl}; # Merge both kinds of requires into BUILD_REQUIRES my $build_prereq = ($args->{BUILD_REQUIRES} ||= {}); %$build_prereq = ( %$build_prereq, map { @$_ } # flatten [module => version] map { @$_ } grep $_, ($self->configure_requires, $self->build_requires) ); # Remove any reference to perl, BUILD_REQUIRES doesn't support it delete $args->{BUILD_REQUIRES}->{perl}; # Delete bundled dists from prereq_pm, add it to Makefile DIR my $subdirs = ($args->{DIR} || []); if ($self->bundles) { my %processed; foreach my $bundle (@{ $self->bundles }) { my ($mod_name, $dist_dir) = @$bundle; delete $prereq->{$mod_name}; $dist_dir = File::Basename::basename($dist_dir); # dir for building this module if (not exists $processed{$dist_dir}) { if (-d $dist_dir) { # List as sub-directory to be processed by make push @$subdirs, $dist_dir; } # Else do nothing: the module is already present on the system $processed{$dist_dir} = undef; } } } unless ( $self->makemaker('6.55_03') ) { %$prereq = (%$prereq,%$build_prereq); delete $args->{BUILD_REQUIRES}; } if ( my $perl_version = $self->perl_version ) { eval "use $perl_version; 1" or die "ERROR: perl: Version $] is installed, " . "but we need version >= $perl_version"; if ( $self->makemaker(6.48) ) { $args->{MIN_PERL_VERSION} = $perl_version; } } if ($self->installdirs) { warn qq{old INSTALLDIRS (probably set by makemaker_args) is overriden by installdirs\n} if $args->{INSTALLDIRS}; $args->{INSTALLDIRS} = $self->installdirs; } my %args = map { ( $_ => $args->{$_} ) } grep {defined($args->{$_} ) } keys %$args; my $user_preop = delete $args{dist}->{PREOP}; if ( my $preop = $self->admin->preop($user_preop) ) { foreach my $key ( keys %$preop ) { $args{dist}->{$key} = $preop->{$key}; } } my $mm = ExtUtils::MakeMaker::WriteMakefile(%args); $self->fix_up_makefile($mm->{FIRST_MAKEFILE} || 'Makefile'); } sub fix_up_makefile { my $self = shift; my $makefile_name = shift; my $top_class = ref($self->_top) || ''; my $top_version = $self->_top->VERSION || ''; my $preamble = $self->preamble ? "# Preamble by $top_class $top_version\n" . $self->preamble : ''; my $postamble = "# Postamble by $top_class $top_version\n" . ($self->postamble || ''); local *MAKEFILE; open MAKEFILE, "+< $makefile_name" or die "fix_up_makefile: Couldn't open $makefile_name: $!"; eval { flock MAKEFILE, LOCK_EX }; my $makefile = do { local $/; }; $makefile =~ s/\b(test_harness\(\$\(TEST_VERBOSE\), )/$1'inc', /; $makefile =~ s/( -I\$\(INST_ARCHLIB\))/ -Iinc$1/g; $makefile =~ s/( "-I\$\(INST_LIB\)")/ "-Iinc"$1/g; $makefile =~ s/^(FULLPERL = .*)/$1 "-Iinc"/m; $makefile =~ s/^(PERL = .*)/$1 "-Iinc"/m; # Module::Install will never be used to build the Core Perl # Sometimes PERL_LIB and PERL_ARCHLIB get written anyway, which breaks # PREFIX/PERL5LIB, and thus, install_share. Blank them if they exist $makefile =~ s/^PERL_LIB = .+/PERL_LIB =/m; #$makefile =~ s/^PERL_ARCHLIB = .+/PERL_ARCHLIB =/m; # Perl 5.005 mentions PERL_LIB explicitly, so we have to remove that as well. $makefile =~ s/(\"?)-I\$\(PERL_LIB\)\1//g; # XXX - This is currently unused; not sure if it breaks other MM-users # $makefile =~ s/^pm_to_blib\s+:\s+/pm_to_blib :: /mg; seek MAKEFILE, 0, SEEK_SET; truncate MAKEFILE, 0; print MAKEFILE "$preamble$makefile$postamble" or die $!; close MAKEFILE or die $!; 1; } sub preamble { my ($self, $text) = @_; $self->{preamble} = $text . $self->{preamble} if defined $text; $self->{preamble}; } sub postamble { my ($self, $text) = @_; $self->{postamble} ||= $self->admin->postamble; $self->{postamble} .= $text if defined $text; $self->{postamble} } 1; __END__ #line 541 XML-Hash-LX-0.0603/inc/Module/Install/Include.pm000644 002100 002100 00000001015 11623443761 020743 0ustar00monsmons000000 000000 #line 1 package Module::Install::Include; use strict; use Module::Install::Base (); use vars qw{$VERSION @ISA $ISCORE}; BEGIN { $VERSION = '1.01'; @ISA = 'Module::Install::Base'; $ISCORE = 1; } sub include { shift()->admin->include(@_); } sub include_deps { shift()->admin->include_deps(@_); } sub auto_include { shift()->admin->auto_include(@_); } sub auto_include_deps { shift()->admin->auto_include_deps(@_); } sub auto_include_dependent_dists { shift()->admin->auto_include_dependent_dists(@_); } 1; XML-Hash-LX-0.0603/inc/Module/Install/Metadata.pm000644 002100 002100 00000043123 11623443761 021106 0ustar00monsmons000000 000000 #line 1 package Module::Install::Metadata; use strict 'vars'; use Module::Install::Base (); use vars qw{$VERSION @ISA $ISCORE}; BEGIN { $VERSION = '1.01'; @ISA = 'Module::Install::Base'; $ISCORE = 1; } my @boolean_keys = qw{ sign }; my @scalar_keys = qw{ name module_name abstract version distribution_type tests installdirs }; my @tuple_keys = qw{ configure_requires build_requires requires recommends bundles resources }; my @resource_keys = qw{ homepage bugtracker repository }; my @array_keys = qw{ keywords author }; *authors = \&author; sub Meta { shift } sub Meta_BooleanKeys { @boolean_keys } sub Meta_ScalarKeys { @scalar_keys } sub Meta_TupleKeys { @tuple_keys } sub Meta_ResourceKeys { @resource_keys } sub Meta_ArrayKeys { @array_keys } foreach my $key ( @boolean_keys ) { *$key = sub { my $self = shift; if ( defined wantarray and not @_ ) { return $self->{values}->{$key}; } $self->{values}->{$key} = ( @_ ? $_[0] : 1 ); return $self; }; } foreach my $key ( @scalar_keys ) { *$key = sub { my $self = shift; return $self->{values}->{$key} if defined wantarray and !@_; $self->{values}->{$key} = shift; return $self; }; } foreach my $key ( @array_keys ) { *$key = sub { my $self = shift; return $self->{values}->{$key} if defined wantarray and !@_; $self->{values}->{$key} ||= []; push @{$self->{values}->{$key}}, @_; return $self; }; } foreach my $key ( @resource_keys ) { *$key = sub { my $self = shift; unless ( @_ ) { return () unless $self->{values}->{resources}; return map { $_->[1] } grep { $_->[0] eq $key } @{ $self->{values}->{resources} }; } return $self->{values}->{resources}->{$key} unless @_; my $uri = shift or die( "Did not provide a value to $key()" ); $self->resources( $key => $uri ); return 1; }; } foreach my $key ( grep { $_ ne "resources" } @tuple_keys) { *$key = sub { my $self = shift; return $self->{values}->{$key} unless @_; my @added; while ( @_ ) { my $module = shift or last; my $version = shift || 0; push @added, [ $module, $version ]; } push @{ $self->{values}->{$key} }, @added; return map {@$_} @added; }; } # Resource handling my %lc_resource = map { $_ => 1 } qw{ homepage license bugtracker repository }; sub resources { my $self = shift; while ( @_ ) { my $name = shift or last; my $value = shift or next; if ( $name eq lc $name and ! $lc_resource{$name} ) { die("Unsupported reserved lowercase resource '$name'"); } $self->{values}->{resources} ||= []; push @{ $self->{values}->{resources} }, [ $name, $value ]; } $self->{values}->{resources}; } # Aliases for build_requires that will have alternative # meanings in some future version of META.yml. sub test_requires { shift->build_requires(@_) } sub install_requires { shift->build_requires(@_) } # Aliases for installdirs options sub install_as_core { $_[0]->installdirs('perl') } sub install_as_cpan { $_[0]->installdirs('site') } sub install_as_site { $_[0]->installdirs('site') } sub install_as_vendor { $_[0]->installdirs('vendor') } sub dynamic_config { my $self = shift; unless ( @_ ) { warn "You MUST provide an explicit true/false value to dynamic_config\n"; return $self; } $self->{values}->{dynamic_config} = $_[0] ? 1 : 0; return 1; } sub perl_version { my $self = shift; return $self->{values}->{perl_version} unless @_; my $version = shift or die( "Did not provide a value to perl_version()" ); # Normalize the version $version = $self->_perl_version($version); # We don't support the reall old versions unless ( $version >= 5.005 ) { die "Module::Install only supports 5.005 or newer (use ExtUtils::MakeMaker)\n"; } $self->{values}->{perl_version} = $version; } sub all_from { my ( $self, $file ) = @_; unless ( defined($file) ) { my $name = $self->name or die( "all_from called with no args without setting name() first" ); $file = join('/', 'lib', split(/-/, $name)) . '.pm'; $file =~ s{.*/}{} unless -e $file; unless ( -e $file ) { die("all_from cannot find $file from $name"); } } unless ( -f $file ) { die("The path '$file' does not exist, or is not a file"); } $self->{values}{all_from} = $file; # Some methods pull from POD instead of code. # If there is a matching .pod, use that instead my $pod = $file; $pod =~ s/\.pm$/.pod/i; $pod = $file unless -e $pod; # Pull the different values $self->name_from($file) unless $self->name; $self->version_from($file) unless $self->version; $self->perl_version_from($file) unless $self->perl_version; $self->author_from($pod) unless @{$self->author || []}; $self->license_from($pod) unless $self->license; $self->abstract_from($pod) unless $self->abstract; return 1; } sub provides { my $self = shift; my $provides = ( $self->{values}->{provides} ||= {} ); %$provides = (%$provides, @_) if @_; return $provides; } sub auto_provides { my $self = shift; return $self unless $self->is_admin; unless (-e 'MANIFEST') { warn "Cannot deduce auto_provides without a MANIFEST, skipping\n"; return $self; } # Avoid spurious warnings as we are not checking manifest here. local $SIG{__WARN__} = sub {1}; require ExtUtils::Manifest; local *ExtUtils::Manifest::manicheck = sub { return }; require Module::Build; my $build = Module::Build->new( dist_name => $self->name, dist_version => $self->version, license => $self->license, ); $self->provides( %{ $build->find_dist_packages || {} } ); } sub feature { my $self = shift; my $name = shift; my $features = ( $self->{values}->{features} ||= [] ); my $mods; if ( @_ == 1 and ref( $_[0] ) ) { # The user used ->feature like ->features by passing in the second # argument as a reference. Accomodate for that. $mods = $_[0]; } else { $mods = \@_; } my $count = 0; push @$features, ( $name => [ map { ref($_) ? ( ref($_) eq 'HASH' ) ? %$_ : @$_ : $_ } @$mods ] ); return @$features; } sub features { my $self = shift; while ( my ( $name, $mods ) = splice( @_, 0, 2 ) ) { $self->feature( $name, @$mods ); } return $self->{values}->{features} ? @{ $self->{values}->{features} } : (); } sub no_index { my $self = shift; my $type = shift; push @{ $self->{values}->{no_index}->{$type} }, @_ if $type; return $self->{values}->{no_index}; } sub read { my $self = shift; $self->include_deps( 'YAML::Tiny', 0 ); require YAML::Tiny; my $data = YAML::Tiny::LoadFile('META.yml'); # Call methods explicitly in case user has already set some values. while ( my ( $key, $value ) = each %$data ) { next unless $self->can($key); if ( ref $value eq 'HASH' ) { while ( my ( $module, $version ) = each %$value ) { $self->can($key)->($self, $module => $version ); } } else { $self->can($key)->($self, $value); } } return $self; } sub write { my $self = shift; return $self unless $self->is_admin; $self->admin->write_meta; return $self; } sub version_from { require ExtUtils::MM_Unix; my ( $self, $file ) = @_; $self->version( ExtUtils::MM_Unix->parse_version($file) ); # for version integrity check $self->makemaker_args( VERSION_FROM => $file ); } sub abstract_from { require ExtUtils::MM_Unix; my ( $self, $file ) = @_; $self->abstract( bless( { DISTNAME => $self->name }, 'ExtUtils::MM_Unix' )->parse_abstract($file) ); } # Add both distribution and module name sub name_from { my ($self, $file) = @_; if ( Module::Install::_read($file) =~ m/ ^ \s* package \s* ([\w:]+) \s* ; /ixms ) { my ($name, $module_name) = ($1, $1); $name =~ s{::}{-}g; $self->name($name); unless ( $self->module_name ) { $self->module_name($module_name); } } else { die("Cannot determine name from $file\n"); } } sub _extract_perl_version { if ( $_[0] =~ m/ ^\s* (?:use|require) \s* v? ([\d_\.]+) \s* ; /ixms ) { my $perl_version = $1; $perl_version =~ s{_}{}g; return $perl_version; } else { return; } } sub perl_version_from { my $self = shift; my $perl_version=_extract_perl_version(Module::Install::_read($_[0])); if ($perl_version) { $self->perl_version($perl_version); } else { warn "Cannot determine perl version info from $_[0]\n"; return; } } sub author_from { my $self = shift; my $content = Module::Install::_read($_[0]); if ($content =~ m/ =head \d \s+ (?:authors?)\b \s* ([^\n]*) | =head \d \s+ (?:licen[cs]e|licensing|copyright|legal)\b \s* .*? copyright .*? \d\d\d[\d.]+ \s* (?:\bby\b)? \s* ([^\n]*) /ixms) { my $author = $1 || $2; # XXX: ugly but should work anyway... if (eval "require Pod::Escapes; 1") { # Pod::Escapes has a mapping table. # It's in core of perl >= 5.9.3, and should be installed # as one of the Pod::Simple's prereqs, which is a prereq # of Pod::Text 3.x (see also below). $author =~ s{ E<( (\d+) | ([A-Za-z]+) )> } { defined $2 ? chr($2) : defined $Pod::Escapes::Name2character_number{$1} ? chr($Pod::Escapes::Name2character_number{$1}) : do { warn "Unknown escape: E<$1>"; "E<$1>"; }; }gex; } elsif (eval "require Pod::Text; 1" && $Pod::Text::VERSION < 3) { # Pod::Text < 3.0 has yet another mapping table, # though the table name of 2.x and 1.x are different. # (1.x is in core of Perl < 5.6, 2.x is in core of # Perl < 5.9.3) my $mapping = ($Pod::Text::VERSION < 2) ? \%Pod::Text::HTML_Escapes : \%Pod::Text::ESCAPES; $author =~ s{ E<( (\d+) | ([A-Za-z]+) )> } { defined $2 ? chr($2) : defined $mapping->{$1} ? $mapping->{$1} : do { warn "Unknown escape: E<$1>"; "E<$1>"; }; }gex; } else { $author =~ s{E}{<}g; $author =~ s{E}{>}g; } $self->author($author); } else { warn "Cannot determine author info from $_[0]\n"; } } #Stolen from M::B my %license_urls = ( perl => 'http://dev.perl.org/licenses/', apache => 'http://apache.org/licenses/LICENSE-2.0', apache_1_1 => 'http://apache.org/licenses/LICENSE-1.1', artistic => 'http://opensource.org/licenses/artistic-license.php', artistic_2 => 'http://opensource.org/licenses/artistic-license-2.0.php', lgpl => 'http://opensource.org/licenses/lgpl-license.php', lgpl2 => 'http://opensource.org/licenses/lgpl-2.1.php', lgpl3 => 'http://opensource.org/licenses/lgpl-3.0.html', bsd => 'http://opensource.org/licenses/bsd-license.php', gpl => 'http://opensource.org/licenses/gpl-license.php', gpl2 => 'http://opensource.org/licenses/gpl-2.0.php', gpl3 => 'http://opensource.org/licenses/gpl-3.0.html', mit => 'http://opensource.org/licenses/mit-license.php', mozilla => 'http://opensource.org/licenses/mozilla1.1.php', open_source => undef, unrestricted => undef, restrictive => undef, unknown => undef, ); sub license { my $self = shift; return $self->{values}->{license} unless @_; my $license = shift or die( 'Did not provide a value to license()' ); $license = __extract_license($license) || lc $license; $self->{values}->{license} = $license; # Automatically fill in license URLs if ( $license_urls{$license} ) { $self->resources( license => $license_urls{$license} ); } return 1; } sub _extract_license { my $pod = shift; my $matched; return __extract_license( ($matched) = $pod =~ m/ (=head \d \s+ L(?i:ICEN[CS]E|ICENSING)\b.*?) (=head \d.*|=cut.*|)\z /xms ) || __extract_license( ($matched) = $pod =~ m/ (=head \d \s+ (?:C(?i:OPYRIGHTS?)|L(?i:EGAL))\b.*?) (=head \d.*|=cut.*|)\z /xms ); } sub __extract_license { my $license_text = shift or return; my @phrases = ( '(?:under )?the same (?:terms|license) as (?:perl|the perl (?:\d )?programming language)' => 'perl', 1, '(?:under )?the terms of (?:perl|the perl programming language) itself' => 'perl', 1, 'Artistic and GPL' => 'perl', 1, 'GNU general public license' => 'gpl', 1, 'GNU public license' => 'gpl', 1, 'GNU lesser general public license' => 'lgpl', 1, 'GNU lesser public license' => 'lgpl', 1, 'GNU library general public license' => 'lgpl', 1, 'GNU library public license' => 'lgpl', 1, 'GNU Free Documentation license' => 'unrestricted', 1, 'GNU Affero General Public License' => 'open_source', 1, '(?:Free)?BSD license' => 'bsd', 1, 'Artistic license 2\.0' => 'artistic_2', 1, 'Artistic license' => 'artistic', 1, 'Apache (?:Software )?license' => 'apache', 1, 'GPL' => 'gpl', 1, 'LGPL' => 'lgpl', 1, 'BSD' => 'bsd', 1, 'Artistic' => 'artistic', 1, 'MIT' => 'mit', 1, 'Mozilla Public License' => 'mozilla', 1, 'Q Public License' => 'open_source', 1, 'OpenSSL License' => 'unrestricted', 1, 'SSLeay License' => 'unrestricted', 1, 'zlib License' => 'open_source', 1, 'proprietary' => 'proprietary', 0, ); while ( my ($pattern, $license, $osi) = splice(@phrases, 0, 3) ) { $pattern =~ s#\s+#\\s+#gs; if ( $license_text =~ /\b$pattern\b/i ) { return $license; } } return ''; } sub license_from { my $self = shift; if (my $license=_extract_license(Module::Install::_read($_[0]))) { $self->license($license); } else { warn "Cannot determine license info from $_[0]\n"; return 'unknown'; } } sub _extract_bugtracker { my @links = $_[0] =~ m#L<( https?\Q://rt.cpan.org/\E[^>]+| https?\Q://github.com/\E[\w_]+/[\w_]+/issues| https?\Q://code.google.com/p/\E[\w_\-]+/issues/list )>#gx; my %links; @links{@links}=(); @links=keys %links; return @links; } sub bugtracker_from { my $self = shift; my $content = Module::Install::_read($_[0]); my @links = _extract_bugtracker($content); unless ( @links ) { warn "Cannot determine bugtracker info from $_[0]\n"; return 0; } if ( @links > 1 ) { warn "Found more than one bugtracker link in $_[0]\n"; return 0; } # Set the bugtracker bugtracker( $links[0] ); return 1; } sub requires_from { my $self = shift; my $content = Module::Install::_readperl($_[0]); my @requires = $content =~ m/^use\s+([^\W\d]\w*(?:::\w+)*)\s+([\d\.]+)/mg; while ( @requires ) { my $module = shift @requires; my $version = shift @requires; $self->requires( $module => $version ); } } sub test_requires_from { my $self = shift; my $content = Module::Install::_readperl($_[0]); my @requires = $content =~ m/^use\s+([^\W\d]\w*(?:::\w+)*)\s+([\d\.]+)/mg; while ( @requires ) { my $module = shift @requires; my $version = shift @requires; $self->test_requires( $module => $version ); } } # Convert triple-part versions (eg, 5.6.1 or 5.8.9) to # numbers (eg, 5.006001 or 5.008009). # Also, convert double-part versions (eg, 5.8) sub _perl_version { my $v = $_[-1]; $v =~ s/^([1-9])\.([1-9]\d?\d?)$/sprintf("%d.%03d",$1,$2)/e; $v =~ s/^([1-9])\.([1-9]\d?\d?)\.(0|[1-9]\d?\d?)$/sprintf("%d.%03d%03d",$1,$2,$3 || 0)/e; $v =~ s/(\.\d\d\d)000$/$1/; $v =~ s/_.+$//; if ( ref($v) ) { # Numify $v = $v + 0; } return $v; } sub add_metadata { my $self = shift; my %hash = @_; for my $key (keys %hash) { warn "add_metadata: $key is not prefixed with 'x_'.\n" . "Use appopriate function to add non-private metadata.\n" unless $key =~ /^x_/; $self->{values}->{$key} = $hash{$key}; } } ###################################################################### # MYMETA Support sub WriteMyMeta { die "WriteMyMeta has been deprecated"; } sub write_mymeta_yaml { my $self = shift; # We need YAML::Tiny to write the MYMETA.yml file unless ( eval { require YAML::Tiny; 1; } ) { return 1; } # Generate the data my $meta = $self->_write_mymeta_data or return 1; # Save as the MYMETA.yml file print "Writing MYMETA.yml\n"; YAML::Tiny::DumpFile('MYMETA.yml', $meta); } sub write_mymeta_json { my $self = shift; # We need JSON to write the MYMETA.json file unless ( eval { require JSON; 1; } ) { return 1; } # Generate the data my $meta = $self->_write_mymeta_data or return 1; # Save as the MYMETA.yml file print "Writing MYMETA.json\n"; Module::Install::_write( 'MYMETA.json', JSON->new->pretty(1)->canonical->encode($meta), ); } sub _write_mymeta_data { my $self = shift; # If there's no existing META.yml there is nothing we can do return undef unless -f 'META.yml'; # We need Parse::CPAN::Meta to load the file unless ( eval { require Parse::CPAN::Meta; 1; } ) { return undef; } # Merge the perl version into the dependencies my $val = $self->Meta->{values}; my $perl = delete $val->{perl_version}; if ( $perl ) { $val->{requires} ||= []; my $requires = $val->{requires}; # Canonize to three-dot version after Perl 5.6 if ( $perl >= 5.006 ) { $perl =~ s{^(\d+)\.(\d\d\d)(\d*)}{join('.', $1, int($2||0), int($3||0))}e } unshift @$requires, [ perl => $perl ]; } # Load the advisory META.yml file my @yaml = Parse::CPAN::Meta::LoadFile('META.yml'); my $meta = $yaml[0]; # Overwrite the non-configure dependency hashs delete $meta->{requires}; delete $meta->{build_requires}; delete $meta->{recommends}; if ( exists $val->{requires} ) { $meta->{requires} = { map { @$_ } @{ $val->{requires} } }; } if ( exists $val->{build_requires} ) { $meta->{build_requires} = { map { @$_ } @{ $val->{build_requires} } }; } return $meta; } 1; XML-Hash-LX-0.0603/inc/Module/Install/WriteAll.pm000644 002100 002100 00000002376 11623443761 021116 0ustar00monsmons000000 000000 #line 1 package Module::Install::WriteAll; use strict; use Module::Install::Base (); use vars qw{$VERSION @ISA $ISCORE}; BEGIN { $VERSION = '1.01'; @ISA = qw{Module::Install::Base}; $ISCORE = 1; } sub WriteAll { my $self = shift; my %args = ( meta => 1, sign => 0, inline => 0, check_nmake => 1, @_, ); $self->sign(1) if $args{sign}; $self->admin->WriteAll(%args) if $self->is_admin; $self->check_nmake if $args{check_nmake}; unless ( $self->makemaker_args->{PL_FILES} ) { # XXX: This still may be a bit over-defensive... unless ($self->makemaker(6.25)) { $self->makemaker_args( PL_FILES => {} ) if -f 'Build.PL'; } } # Until ExtUtils::MakeMaker support MYMETA.yml, make sure # we clean it up properly ourself. $self->realclean_files('MYMETA.yml'); if ( $args{inline} ) { $self->Inline->write; } else { $self->Makefile->write; } # The Makefile write process adds a couple of dependencies, # so write the META.yml files after the Makefile. if ( $args{meta} ) { $self->Meta->write; } # Experimental support for MYMETA if ( $ENV{X_MYMETA} ) { if ( $ENV{X_MYMETA} eq 'JSON' ) { $self->Meta->write_mymeta_json; } else { $self->Meta->write_mymeta_yaml; } } return 1; } 1; XML-Hash-LX-0.0603/inc/Module/Install/Win32.pm000644 002100 002100 00000003403 11623443761 020265 0ustar00monsmons000000 000000 #line 1 package Module::Install::Win32; use strict; use Module::Install::Base (); use vars qw{$VERSION @ISA $ISCORE}; BEGIN { $VERSION = '1.01'; @ISA = 'Module::Install::Base'; $ISCORE = 1; } # determine if the user needs nmake, and download it if needed sub check_nmake { my $self = shift; $self->load('can_run'); $self->load('get_file'); require Config; return unless ( $^O eq 'MSWin32' and $Config::Config{make} and $Config::Config{make} =~ /^nmake\b/i and ! $self->can_run('nmake') ); print "The required 'nmake' executable not found, fetching it...\n"; require File::Basename; my $rv = $self->get_file( url => 'http://download.microsoft.com/download/vc15/Patch/1.52/W95/EN-US/Nmake15.exe', ftp_url => 'ftp://ftp.microsoft.com/Softlib/MSLFILES/Nmake15.exe', local_dir => File::Basename::dirname($^X), size => 51928, run => 'Nmake15.exe /o > nul', check_for => 'Nmake.exe', remove => 1, ); die <<'END_MESSAGE' unless $rv; ------------------------------------------------------------------------------- Since you are using Microsoft Windows, you will need the 'nmake' utility before installation. It's available at: http://download.microsoft.com/download/vc15/Patch/1.52/W95/EN-US/Nmake15.exe or ftp://ftp.microsoft.com/Softlib/MSLFILES/Nmake15.exe Please download the file manually, save it to a directory in %PATH% (e.g. C:\WINDOWS\COMMAND\), then launch the MS-DOS command line shell, "cd" to that directory, and run "Nmake15.exe" from there; that will create the 'nmake.exe' file needed by this module. You may then resume the installation process described in README. ------------------------------------------------------------------------------- END_MESSAGE } 1; XML-Hash-LX-0.0603/inc/Module/Install/Fetch.pm000644 002100 002100 00000004627 11623443761 020425 0ustar00monsmons000000 000000 #line 1 package Module::Install::Fetch; use strict; use Module::Install::Base (); use vars qw{$VERSION @ISA $ISCORE}; BEGIN { $VERSION = '1.01'; @ISA = 'Module::Install::Base'; $ISCORE = 1; } sub get_file { my ($self, %args) = @_; my ($scheme, $host, $path, $file) = $args{url} =~ m|^(\w+)://([^/]+)(.+)/(.+)| or return; if ( $scheme eq 'http' and ! eval { require LWP::Simple; 1 } ) { $args{url} = $args{ftp_url} or (warn("LWP support unavailable!\n"), return); ($scheme, $host, $path, $file) = $args{url} =~ m|^(\w+)://([^/]+)(.+)/(.+)| or return; } $|++; print "Fetching '$file' from $host... "; unless (eval { require Socket; Socket::inet_aton($host) }) { warn "'$host' resolve failed!\n"; return; } return unless $scheme eq 'ftp' or $scheme eq 'http'; require Cwd; my $dir = Cwd::getcwd(); chdir $args{local_dir} or return if exists $args{local_dir}; if (eval { require LWP::Simple; 1 }) { LWP::Simple::mirror($args{url}, $file); } elsif (eval { require Net::FTP; 1 }) { eval { # use Net::FTP to get past firewall my $ftp = Net::FTP->new($host, Passive => 1, Timeout => 600); $ftp->login("anonymous", 'anonymous@example.com'); $ftp->cwd($path); $ftp->binary; $ftp->get($file) or (warn("$!\n"), return); $ftp->quit; } } elsif (my $ftp = $self->can_run('ftp')) { eval { # no Net::FTP, fallback to ftp.exe require FileHandle; my $fh = FileHandle->new; local $SIG{CHLD} = 'IGNORE'; unless ($fh->open("|$ftp -n")) { warn "Couldn't open ftp: $!\n"; chdir $dir; return; } my @dialog = split(/\n/, <<"END_FTP"); open $host user anonymous anonymous\@example.com cd $path binary get $file $file quit END_FTP foreach (@dialog) { $fh->print("$_\n") } $fh->close; } } else { warn "No working 'ftp' program available!\n"; chdir $dir; return; } unless (-f $file) { warn "Fetching failed: $@\n"; chdir $dir; return; } return if exists $args{size} and -s $file != $args{size}; system($args{run}) if exists $args{run}; unlink($file) if $args{remove}; print(((!exists $args{check_for} or -e $args{check_for}) ? "done!" : "failed! ($!)"), "\n"); chdir $dir; return !$?; } 1; XML-Hash-LX-0.0603/inc/Module/Install/Base.pm000644 002100 002100 00000002147 11623443761 020241 0ustar00monsmons000000 000000 #line 1 package Module::Install::Base; use strict 'vars'; use vars qw{$VERSION}; BEGIN { $VERSION = '1.01'; } # Suspend handler for "redefined" warnings BEGIN { my $w = $SIG{__WARN__}; $SIG{__WARN__} = sub { $w }; } #line 42 sub new { my $class = shift; unless ( defined &{"${class}::call"} ) { *{"${class}::call"} = sub { shift->_top->call(@_) }; } unless ( defined &{"${class}::load"} ) { *{"${class}::load"} = sub { shift->_top->load(@_) }; } bless { @_ }, $class; } #line 61 sub AUTOLOAD { local $@; my $func = eval { shift->_top->autoload } or return; goto &$func; } #line 75 sub _top { $_[0]->{_top}; } #line 90 sub admin { $_[0]->_top->{admin} or Module::Install::Base::FakeAdmin->new; } #line 106 sub is_admin { ! $_[0]->admin->isa('Module::Install::Base::FakeAdmin'); } sub DESTROY {} package Module::Install::Base::FakeAdmin; use vars qw{$VERSION}; BEGIN { $VERSION = $Module::Install::Base::VERSION; } my $fake; sub new { $fake ||= bless(\@_, $_[0]); } sub AUTOLOAD {} sub DESTROY {} # Restore warning handler BEGIN { $SIG{__WARN__} = $SIG{__WARN__}->(); } 1; #line 159 XML-Hash-LX-0.0603/inc/Module/Install/Can.pm000644 002100 002100 00000003333 11623443761 020066 0ustar00monsmons000000 000000 #line 1 package Module::Install::Can; use strict; use Config (); use File::Spec (); use ExtUtils::MakeMaker (); use Module::Install::Base (); use vars qw{$VERSION @ISA $ISCORE}; BEGIN { $VERSION = '1.01'; @ISA = 'Module::Install::Base'; $ISCORE = 1; } # check if we can load some module ### Upgrade this to not have to load the module if possible sub can_use { my ($self, $mod, $ver) = @_; $mod =~ s{::|\\}{/}g; $mod .= '.pm' unless $mod =~ /\.pm$/i; my $pkg = $mod; $pkg =~ s{/}{::}g; $pkg =~ s{\.pm$}{}i; local $@; eval { require $mod; $pkg->VERSION($ver || 0); 1 }; } # check if we can run some command sub can_run { my ($self, $cmd) = @_; my $_cmd = $cmd; return $_cmd if (-x $_cmd or $_cmd = MM->maybe_command($_cmd)); for my $dir ((split /$Config::Config{path_sep}/, $ENV{PATH}), '.') { next if $dir eq ''; my $abs = File::Spec->catfile($dir, $_[1]); return $abs if (-x $abs or $abs = MM->maybe_command($abs)); } return; } # can we locate a (the) C compiler sub can_cc { my $self = shift; my @chunks = split(/ /, $Config::Config{cc}) or return; # $Config{cc} may contain args; try to find out the program part while (@chunks) { return $self->can_run("@chunks") || (pop(@chunks), next); } return; } # Fix Cygwin bug on maybe_command(); if ( $^O eq 'cygwin' ) { require ExtUtils::MM_Cygwin; require ExtUtils::MM_Win32; if ( ! defined(&ExtUtils::MM_Cygwin::maybe_command) ) { *ExtUtils::MM_Cygwin::maybe_command = sub { my ($self, $file) = @_; if ($file =~ m{^/cygdrive/}i and ExtUtils::MM_Win32->can('maybe_command')) { ExtUtils::MM_Win32->maybe_command($file); } else { ExtUtils::MM_Unix->maybe_command($file); } } } } 1; __END__ #line 156