From ec7d7a2b8feead992f0f9197ae299fe410ec16a0 Mon Sep 17 00:00:00 2001 From: Thijs Schreijer Date: Wed, 23 Mar 2022 15:57:45 +0100 Subject: [PATCH 1/7] cleanup; delete unreferenced powerpoint file from docs --- docs/lua05.ppt | Bin 304128 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 docs/lua05.ppt diff --git a/docs/lua05.ppt b/docs/lua05.ppt deleted file mode 100644 index e2b7ab4b304505811d6f481ac1ab7147af3e8ebc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 304128 zcmeFYc|6qL`#=1eF)@~yL6)+NF=%>Ag9>FC4B0{?Te8GdWX~Rk1|za1nTV7nWXZlH z>pNsiLYARH)+`y4{hoP$d*8qB{rTO$KYsW9&;7@Jd0d|7y3RS*xn9>Fp(9`3fKMEKCOwrQ}@!;_AkfHrX7bfXEL1zk`_vlQ| z`v2+w!w~@Tx!CAk$3kZ?zzP8XEbxlUjV>Jl4)@jQh(rK@BOL*H7ypBdG=K#&{xfPF z9$3*k)(G!y*hvZAsDHD(pd0+)nMrDnCzGsYDSs>A<)|d04{(X@`9e?0)VyD ze>BW%3G`Cn4iMl;&!3^Q0;3?E=p*kRV))IVe~Qx)`i}(spF>vQkNj^wqfv%KJpZBR z_#^*2)LH*S=KK$t?&Cl7Z~6ah_djKZpA6ssSLOfp?|+4iX~&>{>;JFH{om;s*DUc* z?f(&{qkm+EpA6d!WYqo7`v11~-;r@GGIVCdj8UEu8-|Y2@Bj2Y9T|G|Kgei{Av0pe zKt}8t$RLJYUONA0y#H;FQSKO>8OTRxhMv)<|2?0dE;I54{~#UyFZTbHkJA$;{xGAw z5S>lXu2e`HBIGRiTC zp=ZPnL1zXr>M`hFWW-O7&WtuNe~>ZF7;VVYnNbcwXNDayIy2<6e^C4nO8h~oKX~R3 z%KpJ~bY#>&|3^MaM}~jsKeF^6`Sc(8)F1ro52^v6H6lF?23Xcmbo`&`pF6>SQ#bu@ zm38=ImzlZY0@mWkiR%ZF;)YhCtZzRb0-~*qcK@X&-~qtC#)wlGh#m>(1IE;bMyfON z8$mGoD$xX@tDt}Xqd5dY>Ej#(rq_ph0LOna`u~s&0E>%@0EI$fRH74s&L8P~2w(w` zpMS;xlwpOjf^X569#LS8i%}N_wF_7UN7qG*0i%|(UU}DVGe`ueH(XEdE!9b}Sy~2Odr@q5RMyiyP z3zR^2jX-CH>;ddDF@`FGJm`skWky9TeNKu3JP_r7a{q0E3z%nGm}M-C3rvi`K%mdG zZ}cl?FeA+v9E=Ihn23x?|HlOo7qHHxO~2wZKnE8?j{!b&F#^HJ=K=;%O?-Txt*zr}*C8{bI0F2)Ek z4EQfwSLv2q0Vlxw|Aj5YA6uG$JK*z=Z%*|82*8kT_kY(f%pY6kbidqyTl8N0FJ$=l zzhetbzeemITc;1@4-o+7umV$!`F|2G0^Jq>WdCzxCjfTzG-LPzK+ZosMHiurWr(q? z(8*0?jh{ZT{-@~{ZESeyDBE#H-yhZ0!I{vpgU%nI^iBr^Fc!6RVD-?kq+cjI4}(F# zvvkJt%yLinvKGrA3meZx4*!W9FUF#!i&MYqKl-D=@-b@IN7BD4s3ZtCWAYc<33X|d z4k;NYu61R+B7qluWhyuE?5mWXz5amIs*uzu@@$DV1vLF!%0D(XP2ypQs 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 z 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®xYxHxE52|t9BMwyZy>%OG$2wW#LK+X`!@%#>gAxNIDt z=ISJ;V`Td^0X=6q-7G(F9|=)^4he|5*&o8kArtyTN<2>6PiA`N0U{)dK^p&1kEG4F z8KC|S6D;?!S`KNEUn8x5=;z?ZsN_gUS^9I*AL1F8n~0wFG;r`HAM17NX_rmSqUcVsK(d?&Cw3R+atfwEGi6f7ssf z(Wd8jwV&~-Ka}IU1_miaxtV?&@^VM!I_O`_Ob->z^gC-g)2|Z~ zzgCo5N`>m4>6i?5%}P|L?wLOM5YP18c7J-&pF=X!3wDLvGrhiOrtkgx!Orw~)0J|M zkvG$UfLc%elAr0kW@+>@oyw(BYx?C-BXg$rVr$0C^kBhEzkDiZdT%|kteTmgzxNs# zLUVKL-jqW;)7|}Hf0M2?x1o3@PV^n*n)^$vxxcev__**}-kSSTn~7(VxY(z}k-z5k z>GXNpaH(~*K0Jm?B)tJT&v*zOvwlyA!A8E~fDZR1cb%NHDmZ|{2s?7d96)sOL5Vdw%hq@Yi` z3DX{)J7?O{DbZ@I{bX)ula;f<+c3>ZPRIO)DRn;8Drr63@iyBbtcoLXq87o!9Zjfd z9I*&6@eDPp+o+>lS}pFlH-}CGS5Qvp&Vyq|(z!ndZiYJdN8yKTojX_7+TStUKXjGE z=j++`p0u1iotljw7i%M1E9BuyVq|fn53WHtr3A;6uK#ZTA&?JtqHa^C->%cqL96%r zYX^mgpoyC?tuzutNRE7D_@k0WA57%)yQK%cX;fQuFcC9Uk{)IvfoT`vn*X6XVTP|2 zKj5z|v@&)Mq2!tA`Xk)@!x%fKJg#=kxJy0=ZWYKETaM=#CB)|&Qq~W>0bxe^lWs%$ zxR;!I9Cpl5lhELTYA~Aoc`iB5ww}6#Nk<%r9AC{2zWn%HsJGru1>vWdN_Ld0;xm0#erlPGyzCqxJH6v}HxfUiQ z*Jl86{2J7^cJVY#3>}<4PlMrHHugb*WBR}`D7CDH+9!-*S=}vX9Jk0q--}`5r#oHZ z-y$DdRZ_)i?7T17A}!7>z7@4Gw28k~(w958^>T^b6YSKb;xDn^?euNPPKdsK)cu}M z7@ZTkS^FEYRDvTxR~9cW)Hf?S*IqeSEXqx)ykgPf zjY6^L()x|@&A5OFcMHYReYlrPu3Oi)eDT&iT$t5HVP`Gs1-nlNa(jhZr=Jy1Y?ASm zJpf4ZDxw-Vj zV=t5ve?Iu`um7Vb{$ON1@rSIf;C*=o@i8y{knPsO&%uj7w*6U=_@jvo$;>nU>tM-I zPW<6jQ6q^zv!Q9E_%jQByIcGLYfJIxb705GmXq-{Cm`Svu6+f5%jxIDALJ=1{vbSG z{88UJ6yncLw91fNzg?#z{_Onr!HPdxQ`lQ{L?FkblBTd9Kr!u_fOeGhH6*6ViFi#@C@DKgMVV$K>#)fDQ`5|hWya}+&x9(1q# zl^=-n@T3?|FvsiV$csXjo}W1u?lSP2aol}{Ye}QB*MMb1*%vQj+MB(GE+Hyd%s@q= z_-PVj_8ht}4h#``L#+{h`udQP9++)Gr#~yerIEc`)1DyU!6`YQMsXksTIN3E2jv^LZs>L6&;CGx?o&~3+;7BZZ z8}?1ff}a7u!)C#GO2CPhPj%n}IWk8iYGks=yO0o)HUAjYx}{ljB(PnMHAh*7HQ$9e z!;aP za3AN^U{5`xyft6EvYj{b4_aYPN6bH3zx3C2o9cd~gdFm(tSxfB%$AeJ9W8lao8ES-5!Rv&LFIHg4>hVYjm!_85yb2Zt)3 zu&J?UQ5{>@R5kWcpW<$zdu9dD!u*-F^QVO~i}rH)GfV5jo*MNxH#~;ejN$R9nYu7X zM`t}f)ArX~A*d!g@jx za_)WRV3D)6F5P(Yj7FKZ)gb3I4>@hBC2W~_1_=RR#2uXn&2o`0;0UWXUhf_d5$SG->VyWk=&t&i5bZW;8s$fBg7ydRTz{W(zKX54cdcRh~GVgc6pOwZlijEjoZ@SFn{i-prx1^QY3 zR`WT~DFuZvBS4eqxRpUI8^5CAcX_$5QuGpaWSma^2QKObU$HQx5Gw54Xg&ve&p4OM zHgWWB7AQNT$8frG?e#u-)kmFIb2=^eYO39T<5(Qjr&*K*t2|@+n72*jCemmI=Ab6Y zC` zLUgQz@T{8%zhRuq)%C7A@QzWge9MtB$8s=l71Wk`esrOWv>j?4RKgj${v*beqIs7jv^NR1v;%s5KE+!=wz`KXc}OFqJbE8uABV?Gjv zvE(Dxjy50rHa$jH~kNE;K@AC_U=YM`-4c1omVN=H#K5Y7DG|E`v zuotY^`KGY*jkRMuA+prRA%mm-I3&+T2(3F@HbUU#i%(xErROOJF7io-y%)`JwBJ*G1 zcezgb3AAfueuu>zXhzfT@VWL`7sQ-3ameU_PO zgfWdf-)Y|qdIQFk=Y#M4_T(`fWIBjbfA-C|Tu%K70jFr@RxAE3jU7Z69QnzQ#@!zw zo0EJjMyvaR^4+HXmYe|rv`>60f;bgkC9ma9@L4RedxGua^AGEDyYeUau=Fcf&4>q+ z>Kj~|Lamb8JBdX;RQ68np!`-<-NDNcwkaJ>W_nWT zJ}VlF-~fDmNMt;jORfnYaq08SsA%_p|eUFU?N zI@@nAth4wI4C~++Hq?0}BWK-Dal+DXz61`q_=F|GaNHTT2)`jh7`6$W8aaOjB3Ou=!Y#5la2xQ;Ngv2#kkc)F)F7P5xe>_8^KVI?h@$&GGi3x6 z9gFnwDU_X?7OWX8(X*)e3WVPPx=5C2|L3NZVB2m2yj1QY$THWu)Sx4^`YIKD#Y-uv z>{R$kCp5AUn!`ZOa3kDaF-7zbcjHIHmsMWF} zoQa*gXztSbSBH~XM(P+Vm7JIDjm_&xY!}Y=0@QFND;6m*s*eOxT{1OW7#irpk4-+2 zZ?$+UbC@IBip36Ygu@(3g+U?Ap(;1Bv$Z$*K&Wfq>3jPJZ&i2te)4dydc=3|m-UW? z51tHGL%neC-h*N_M#Bf+1M*Og)i?pb8Hv@n6KTk5+y;Np%?DquS&i8eU!`scc?_$u z4dY^#&KiW1)rerhpN()$xxs2IpIU;|$X~k26OV=A$m5Ca`W-&Jb7f)8rzU^Nn=ehjN75%mM`ce)TYaFs^Xb0xk?L`5EhsChgw!ilJb zJaPNpLUgGi9v|fO=Qo4xHdBPXaDM}S14<`P-1W>*BUZZ#bT8$@MWWjy-9Kr`l5ev1Cj0*=#}PY&URPt>$#|+_?^jbav#+ z#?pmFa}fICeX%xezR}X$Ep{EvuI#xaThrlwCqb@tbLD9+lUY{%^-A3nyai*=O&Dyq zV1_lo;`#r{zKecaEpa|S2AQeLZ+J#R_U9GkeMcgZSu`R$Se~wmmwBHEEB^0NZ;(0`02W_X{>xL zNYP?a%wR|>Lh$W@uA8TO``QtLj}dhU?;i9mLI}Q7&>^QWWHCY(n-Gg3%Mh~6gm5R% z2O|i=Md#vPp)Y_CKt_kqy4_cc5Wq%qZI<{tmyo_{bd8?#q3eo<`cHTx_g^fHiDwheY@)?!C0(jZfmt-+pw(bIOXsyJf5Ded=rul-Xtml~ zEt3VsaBu>jgb4BXnOzNLC~23(h8@$p ziOf=x&qXM7om9qUJt}NAzM>c0l~1k$T^KY_D@`hMChjDnU>hZ`!;BZP+9ae^vDyc3 zCH!lU9r7PP74lP_8+t_I^-%|vSnUtK`|JP6FXz@v`Z)(I^p;Lu^`rh<&2=bK3JPIP zjrLAS#)I<_sx>3OhHN>rnnzpy5E7WzvncT;}EI9n{fa zY*Q77!ZTU!P83{)cTE7i`k3#EL;SbtE ztHA#uEwo-O@m1Q}BM*|Jyui>l_=ba5iS0 zxpuCtZD$;0OiG&r;k8#sdSj6-2y0o}YR$(-dz3RXkRGqjT5RcHrlHDaAq!fqb(gKh!x@s_F4CPj5k@)ZTe^(1bT!3QXi?Nvhf~GE zR%_*kwX5x-r5h^-dU|4Mt6Mx>n1nMRo{UTP&d{-TwynKTms>5m70WC(%8}AFfJ9ZF z0Qg#ThtE387WZ}A(8atGrNaJ!Om8}t8AxPXiej&3WOAUdJC-J-P>J0ZTW7FfsaBFx z>?U;q8zV~c)rx~!jo8gxl2OQIo?@0!9=EvafX6Kou~aehq?wCV2Rv>O;5n+fMND;J z6~}{HL|Gsl6}iR63f$t$ka;9-@gbXA{2cr)7q=MroaPqSj)q%Ao|4=m!b@?B*6{H& z4;8m~r<+?u{iV3YU1v>)*3;t_g(hLq^0qj}@U4LC8CCw)gxn%FisACP#rFXBPK(CC zBgLrripFuOL#!n-*J_Da=bsNY%Xc^aM4A@+WcXbEOd)$VZ_zE{H9&6nZackvomFS z7-sMqjG18#mn)87HLT%#B^`4XDH2JWJl4=-4a@4)Jl2r&#&$lWKG=$pw9%#l%1!$e zL^EpI&soACe@QkG;icHbt``c=K^#9zm^-j68>Qj|)bC~!2XU@WeeIi|j8*C_gtod7 ze~fDJ5v&Ly*HIp|_7?dLKT|fU<^wbdlRX&#DkQc;`zKgFYtmD)Vg5BFgEYDvW+KD4f{h(<1ALaGY6?vk z{}|f<7Z8rj;8EXW7(C7lrFI920hv@}ODxMBN$&mX9YtDN`ph#zwb_Pa@W+|-kP9;> z7GY+8{rF<$P+doDM}v}M4gV+@S;Atg15LHv1hiixgKG7#*npzy<4bz&<4d{#PLdam zFwP#?6t!HAE(yy4Cs4-QU^jbcqyMD2N-WkEb6QL>SWKUWN(P5XyWs?f?Pt7d9Ok>m zi$WZpRD{F(8^;%iyCxHd`=`Mmh1>)urh~!u zQXo{=EDMGTJ6$FfzTJhvlZ!BT*U96H!CjNPf?YE-74~@CmlkDxMG36rQXrPihP0CD zg%iZIpYf{M1HS7ugot??-fC*5h-g$t#KaMK=6qPU*u^~pidyh$|4SgsvlETL<+rh4 zi&#%gv?g`bJ~5F@Kr6~G_31&N0};0KqdmGsWMuQ(R6kB_dTLU~)Q+iLave?CHt88J zt(sDyO$}(%;5fjkA1&&bI#gFJoB-{za0;SL9pliZ-YFdoUBO;C?Y%6VI?Tw4ReD~V z?m*NEpT?(?(58LZ8#CAUxbbNfE#1`(77(0%*Bg zb~2$gZY{$&qGcnDqYJkt7PM>)AYl|BKD6v$bkXb8grPx{=TpbYwHaKns8k`_#QANO zB@@q4U>rpQ&NZf|Gx4Mr6nz;_yr*Lt6Au!jxS%nfILH*NBcz5VS@7wgaKqn0@q2oP z)%}kv)%|djx_jZ>pba}3=Zli-md3g8E2&>5OZ>>jwXGBWuZLEUbNTV4%be6EQVi6t z8spmk5oOJs1D44IUxUF3phl6x-4ShE`;Q_g=68f$D1-_-XKX?%*;=yGgffp0cSD(P zbYm@-c|GIWpgQxwVY+vh)1QM$S82e_z}zh8Up*o%LdFi?iUY(G(auz9^;}I`o@1k2 zQ=D%^JU8;OxkrnkGfA`_32!V&z5UnX@Zb!7-O$3t5O5gh1=*L;jKwzv>8hU>=nV*6 zd1HP(A6Fe180T_zz24UghmF9Je;N%Uc?6ay>T=_Fhc-F?(Tv3}$p9BDFbr`oFnk{^ z*Yvh=E|+caxTeFnI#A#l4I+7ynkedW<2b1)n0jMDp?k%F7n^IM62KdaBV#P6(5ZGT z_}S!cOwV$kO_GVhB3HrMsrD?r-KGuicjG)ODx_PaKOf9GAtW)3FRq~FZkovTkI5h%<_z!nqaHse=BZ+_xSK6c+ z#uGL_bXe~)GVP>Elxe3{2pn1M1n3S6oD4jgUGTWP^0;Z7)0bWC6`MHDU8VHh$pmUc ziMx{-PCVa=#m3oI`4HWPY~o>Z{|) zXl&b(&FNSy+k$iRajd;Qe#br_7l+^C?4L|5(bJagUm~XzwKOkiYiri2@P&9Xm9^4V zwiib(+8<6Q;|XTtnYb2Qx}c0yUmw0VZ)sk0(c1ORtvswhS7}wn>4SYsHpxCOw+`~> z&q-?RgL|$}r}H^?o_z>=RCv#wm#c4hcAwdf*vJa`*OyfGq-mcemlD%E8 z>m+--=EbN9C)u+m+T3oy-&HIPKg}cR56~tDrUj%W5>B`{;XI&Qr{9zpE-|!2yZ-yo3u;Hlu(ux;0#&&+RR<~DwiuNR4 zD6%h>`0~eP&XoAWb$Iw{Y2ru<1WQsig=Xpw)e@)S00o~>Dex;o3qQu_SnWTJcN#?6 zkdY`mUQDLVGf9MbrsC8*JHxBQs_yWA-a|ATd7;GE)(_pvqy?vG%tOegSTvp*$bj~w z)2X!8pH3xXt=6^ibSfK&?i72Rh7{sA3^Xb?Ir$M}h^vdxJz5 z#yS&)kkioPgjj<&Ga-DO5Ew9H%zh)2VG>}<)xOjB_7C2w?)3fS;a(UYAN=XCz1Ykr zx_8N@etC57kob`eSpV(h>nv{O-$nZ1GCr`C>vB#T7c}@rR|pk$ZZrn0-g#d(5Z!md?~Odfpu&CcNeH*lPG{eH=+uToyzkBS=hr!ST49}f-`l_OR0ijx@U+N7Yq zvGOLx%cL|Y{^ep>dy64&lY+Wq_m#ULB^T_@!Zrl9DF|hIL%~7_cvBt1zs{ArWRCQO zwH*w{PwPS*eJGh(9gYjQTzXO|hslL?PQW(|DcS0LnJKj3Zw0KdTV~ofnOC$Nq|8Jn z7yvmOy4e>`W*WsMx$mtY(4PcYjU+R@9cd^ty&1mcIzfKIN3_huJBzB8nUJTX%!KfK zndzzXpDRF=@jDdMjiT&DK8o(@TRbCQT63eQHfKIa6h)mceH5))tRM0}19;%>U_aza zH3`q8IYCtyND6Az4E4b8u*G%ilKgua?;mSDep8s_QTUmfw550a;e)$vJ zMnke8(Zr zFp93l_Z3vLT!?dRdG4=1S_KLjgh6>RI4J&uPyIqI#E~lM?z`39kFnkzvH?rMwOvw_ z*BI%(XpPa6`>#=hZ<}yMP!0M2h}zAlPr_F^N)6e6)=HO%MRgyr%(# z8GAp%Iq#q6pw(#QtWf)>^w_@>;f0I_zh-&tm&0}aC*OZuSJVB+<>o!|lpK46kKfpH z!{1O|zg@DkC($4J)Z~0dq8tsloZWPN7p1BFj>Zmzlfrf~8egZ7lDf|TpRY)JZ?!4# zeZdwc(>4v_YdTT-12L9+tt2m}K)qaI_Zamp-ZUkbVEHq41uARr<^ne2H#f^9Ra0n@ z_)_h$Wi}&A{)qOa1dIn4ilQ!s0)axV=^texI9wCYZa;vyRpD#n(N=3~Z^}xEYY1BNYk!pOER@JV{KTyGGldbw_@A+W9fJ-89~g}-dH*o&R7>)sbpe1OeDim z8cX)I;TG#OE?``}sT1av>1%Oo;?{ILn}r!=cQ~?zqF*@m5OSUs3qw59|#$78*Tp#`UGDMaWZfDMI-8Ek)O0smLuwcFE3C^wb3xPpxh#qD5w@rRX{I zi$uGF(G`{=OXBYnb2>Z%PU6V3)5*8WEaz47T5joCEU|lnT;8;+e(7Q9mq>LZS!2$Y zR865-cH>Z!M?yJbB}nKrfl)pQeHck!-5cg*w${c=LGr@M?Ib*H^_ybbvQ}Rz8l#D3 zHWf)F+N_OGk>VCJu@i>{r_f9xis@K?A|697Qq6E8ld=Xfpjx1(RwfMEH2`DwbYeSc zot>SOZ6J~zNP`r^>Rgh>`}z~HzE~0l@bOgArj%B8Yl`g{NT9$Bt_A}ov@!$TneCY@ zs5LdVBz#}OPdjeD(w)OU1VtdjCn1N1^f9%@m?F}LiFdS+zB3{88`9T+?ieooUi6iu z??dq0-K6jTH0fI+@%f~WAac7L=|i59qz~caNBVZ7={eG8m+X+f_7l3QBzdkcU;;plEZI_md$a`m zaW2BvKn^4OAgP)j}jz!}A5c+TnYdn)}wfe)EOf1S|VJjQ%PQ=>kFV0$9Q|T=k zR0avH2cM;6`XH;JK(Zo{oJ`kNzXDR;R^gXKjN_HAkPL-=N`%v!V{H&VZTXKawZhqK zIMPd=CS&0?SIB!1Dj`#b6DV|ZxO;mRTumaC+}u`=K1EZ>IVeBOYh)qMrXZ41WX!Tc z^c_F}D-`QXrMC;;vj(t#xn^VVbd!yeXVNEL2Cn22)_PSd2rFV>3&TQP_%VrO=I2WI z-78<(kdM$sG9{562e{)?G=}N$B8~~`^^wdmHBo1M*`Gf|o%K[~2ha~#t@A)Fl3 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

q3K#UGuE*q~9)O#l@#|#4d9-E2eW2P*||? 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 Date: Wed, 23 Mar 2022 15:58:50 +0100 Subject: [PATCH 2/7] cleanup; move logo file into docs, more appropriate --- logo.ps => docs/logo.ps | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename logo.ps => docs/logo.ps (100%) diff --git a/logo.ps b/docs/logo.ps similarity index 100% rename from logo.ps rename to docs/logo.ps From 7187be8b76452aa968726180af24deaaa545431d Mon Sep 17 00:00:00 2001 From: Thijs Schreijer Date: Wed, 23 Mar 2022 16:01:50 +0100 Subject: [PATCH 3/7] cleanup; delete the ./gem folder --- gem/ex1.lua | 4 - gem/ex10.lua | 17 -- gem/ex11.lua | 7 - gem/ex12.lua | 34 --- gem/ex2.lua | 11 - gem/ex3.lua | 15 - gem/ex4.lua | 5 - gem/ex5.lua | 15 - gem/ex6.lua | 14 - gem/ex7.lua | 16 -- gem/ex8.lua | 5 - gem/ex9.lua | 3 - gem/gem.c | 54 ---- gem/gt.b64 | 206 -------------- gem/input.bin | Bin 11732 -> 0 bytes gem/ltn012.tex | 695 ---------------------------------------------- gem/luasocket.png | Bin 11732 -> 0 bytes gem/makefile | 14 - gem/myps2pdf | 113 -------- gem/t1.lua | 25 -- gem/t1lf.txt | 5 - gem/t2.lua | 36 --- gem/t2.txt | 4 - gem/t2gt.qp | 5 - gem/t3.lua | 25 -- gem/t4.lua | 10 - gem/t5.lua | 30 -- gem/test.lua | 46 --- 28 files changed, 1414 deletions(-) delete mode 100644 gem/ex1.lua delete mode 100644 gem/ex10.lua delete mode 100644 gem/ex11.lua delete mode 100644 gem/ex12.lua delete mode 100644 gem/ex2.lua delete mode 100644 gem/ex3.lua delete mode 100644 gem/ex4.lua delete mode 100644 gem/ex5.lua delete mode 100644 gem/ex6.lua delete mode 100644 gem/ex7.lua delete mode 100644 gem/ex8.lua delete mode 100644 gem/ex9.lua delete mode 100644 gem/gem.c delete mode 100644 gem/gt.b64 delete mode 100644 gem/input.bin delete mode 100644 gem/ltn012.tex delete mode 100644 gem/luasocket.png delete mode 100644 gem/makefile delete mode 100755 gem/myps2pdf delete mode 100644 gem/t1.lua delete mode 100644 gem/t1lf.txt delete mode 100644 gem/t2.lua delete mode 100644 gem/t2.txt delete mode 100644 gem/t2gt.qp delete mode 100644 gem/t3.lua delete mode 100644 gem/t4.lua delete mode 100644 gem/t5.lua delete mode 100644 gem/test.lua diff --git a/gem/ex1.lua b/gem/ex1.lua deleted file mode 100644 index 327a542..0000000 --- a/gem/ex1.lua +++ /dev/null @@ -1,4 +0,0 @@ -local CRLF = "\013\010" -local input = source.chain(source.file(io.stdin), normalize(CRLF)) -local output = sink.file(io.stdout) -pump.all(input, output) diff --git a/gem/ex10.lua b/gem/ex10.lua deleted file mode 100644 index 2b1b98f..0000000 --- a/gem/ex10.lua +++ /dev/null @@ -1,17 +0,0 @@ -function pump.step(src, snk) - local chunk, src_err = src() - local ret, snk_err = snk(chunk, src_err) - if chunk and ret then return 1 - else return nil, src_err or snk_err end -end - -function pump.all(src, snk, step) - step = step or pump.step - while true do - local ret, err = step(src, snk) - if not ret then - if err then return nil, err - else return 1 end - end - end -end diff --git a/gem/ex11.lua b/gem/ex11.lua deleted file mode 100644 index 79c99af..0000000 --- a/gem/ex11.lua +++ /dev/null @@ -1,7 +0,0 @@ -local input = source.chain( - source.file(io.open("input.bin", "rb")), - encode("base64")) -local output = sink.chain( - wrap(76), - sink.file(io.open("output.b64", "w"))) -pump.all(input, output) diff --git a/gem/ex12.lua b/gem/ex12.lua deleted file mode 100644 index de17d76..0000000 --- a/gem/ex12.lua +++ /dev/null @@ -1,34 +0,0 @@ -local smtp = require"socket.smtp" -local mime = require"mime" -local ltn12 = require"ltn12" - -CRLF = "\013\010" - -local message = smtp.message{ - headers = { - from = "Sicrano ", - to = "Fulano ", - subject = "A message with an attachment"}, - body = { - preamble = "Hope you can see the attachment" .. CRLF, - [1] = { - body = "Here is our logo" .. CRLF}, - [2] = { - headers = { - ["content-type"] = 'image/png; name="luasocket.png"', - ["content-disposition"] = - 'attachment; filename="luasocket.png"', - ["content-description"] = 'LuaSocket logo', - ["content-transfer-encoding"] = "BASE64"}, - body = ltn12.source.chain( - ltn12.source.file(io.open("luasocket.png", "rb")), - ltn12.filter.chain( - mime.encode("base64"), - mime.wrap()))}}} - -assert(smtp.send{ - rcpt = "", - from = "", - server = "localhost", - port = 2525, - source = message}) diff --git a/gem/ex2.lua b/gem/ex2.lua deleted file mode 100644 index 94bde66..0000000 --- a/gem/ex2.lua +++ /dev/null @@ -1,11 +0,0 @@ -function filter.cycle(lowlevel, context, extra) - return function(chunk) - local ret - ret, context = lowlevel(context, chunk, extra) - return ret - end -end - -function normalize(marker) - return filter.cycle(eol, 0, marker) -end diff --git a/gem/ex3.lua b/gem/ex3.lua deleted file mode 100644 index 60b4423..0000000 --- a/gem/ex3.lua +++ /dev/null @@ -1,15 +0,0 @@ -local function chainpair(f1, f2) - return function(chunk) - local ret = f2(f1(chunk)) - if chunk then return ret - else return (ret or "") .. (f2() or "") end - end -end - -function filter.chain(...) - local f = select(1, ...) - for i = 2, select('#', ...) do - f = chainpair(f, select(i, ...)) - end - return f -end diff --git a/gem/ex4.lua b/gem/ex4.lua deleted file mode 100644 index c48b77e..0000000 --- a/gem/ex4.lua +++ /dev/null @@ -1,5 +0,0 @@ -local qp = filter.chain(normalize(CRLF), encode("quoted-printable"), - wrap("quoted-printable")) -local input = source.chain(source.file(io.stdin), qp) -local output = sink.file(io.stdout) -pump.all(input, output) diff --git a/gem/ex5.lua b/gem/ex5.lua deleted file mode 100644 index 196b30a..0000000 --- a/gem/ex5.lua +++ /dev/null @@ -1,15 +0,0 @@ -function source.empty(err) - return function() - return nil, err - end -end - -function source.file(handle, io_err) - if handle then - return function() - local chunk = handle:read(20) - if not chunk then handle:close() end - return chunk - end - else return source.empty(io_err or "unable to open file") end -end diff --git a/gem/ex6.lua b/gem/ex6.lua deleted file mode 100644 index a3fdca0..0000000 --- a/gem/ex6.lua +++ /dev/null @@ -1,14 +0,0 @@ -function source.chain(src, f) - return function() - if not src then - return nil - end - local chunk, err = src() - if not chunk then - src = nil - return f(nil) - else - return f(chunk) - end - end -end diff --git a/gem/ex7.lua b/gem/ex7.lua deleted file mode 100644 index c766988..0000000 --- a/gem/ex7.lua +++ /dev/null @@ -1,16 +0,0 @@ -function sink.table(t) - t = t or {} - local f = function(chunk, err) - if chunk then table.insert(t, chunk) end - return 1 - end - return f, t -end - -local function null() - return 1 -end - -function sink.null() - return null -end diff --git a/gem/ex8.lua b/gem/ex8.lua deleted file mode 100644 index 81e288c..0000000 --- a/gem/ex8.lua +++ /dev/null @@ -1,5 +0,0 @@ -local input = source.file(io.stdin) -local output, t = sink.table() -output = sink.chain(normalize(CRLF), output) -pump.all(input, output) -io.write(table.concat(t)) diff --git a/gem/ex9.lua b/gem/ex9.lua deleted file mode 100644 index b857698..0000000 --- a/gem/ex9.lua +++ /dev/null @@ -1,3 +0,0 @@ -for chunk in source.file(io.stdin) do - io.write(chunk) -end diff --git a/gem/gem.c b/gem/gem.c deleted file mode 100644 index 976f74d..0000000 --- a/gem/gem.c +++ /dev/null @@ -1,54 +0,0 @@ -#include "lua.h" -#include "lauxlib.h" - -#define CR '\xD' -#define LF '\xA' -#define CRLF "\xD\xA" - -#define candidate(c) (c == CR || c == LF) -static int pushchar(int c, int last, const char *marker, - luaL_Buffer *buffer) { - if (candidate(c)) { - if (candidate(last)) { - if (c == last) - luaL_addstring(buffer, marker); - return 0; - } else { - luaL_addstring(buffer, marker); - return c; - } - } else { - luaL_putchar(buffer, c); - return 0; - } -} - -static int eol(lua_State *L) { - int context = luaL_checkint(L, 1); - size_t isize = 0; - const char *input = luaL_optlstring(L, 2, NULL, &isize); - const char *last = input + isize; - const char *marker = luaL_optstring(L, 3, CRLF); - luaL_Buffer buffer; - luaL_buffinit(L, &buffer); - if (!input) { - lua_pushnil(L); - lua_pushnumber(L, 0); - return 2; - } - while (input < last) - context = pushchar(*input++, context, marker, &buffer); - luaL_pushresult(&buffer); - lua_pushnumber(L, context); - return 2; -} - -static luaL_reg func[] = { - { "eol", eol }, - { NULL, NULL } -}; - -int luaopen_gem(lua_State *L) { - luaL_openlib(L, "gem", func, 0); - return 0; -} diff --git a/gem/gt.b64 b/gem/gt.b64 deleted file mode 100644 index a74c0b3..0000000 --- a/gem/gt.b64 +++ /dev/null @@ -1,206 +0,0 @@ -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 diff --git a/gem/input.bin b/gem/input.bin deleted file mode 100644 index d24a95495b55894b96aec1b01d0b7c02cc43f168..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11732 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 /dev/null` - then - ofilename=`echo $1 | sed 's/\..*$/.pdf/'` - else - echo "$usage" 1>&2 - exit 1 - fi ;; -*) echo "$usage" 1>&2 ; exit 1 ;; -esac - -if [ $best == 1 ] -then - options="-dPDFSETTINGS=/prepress \ - -r1200 \ - -dMonoImageResolution=1200 \ - -dGrayImageResolution=1200 \ - -dColorImageResolution=1200 \ - -dDownsampleMonoImages=false \ - -dDownsampleGrayImages=false \ - -dDownsampleColorImages=false \ - -dAutoFilterMonoImages=false \ - -dAutoFilterGrayImages=false \ - -dAutoFilterColorImages=false \ - -dMonoImageFilter=/FlateEncode \ - -dGrayImageFilter=/FlateEncode \ - -dColorImageFilter=/FlateEncode" -else - options="-dPDFSETTINGS=/prepress \ - -r600 \ - -dDownsampleMonoImages=true \ - -dDownsampleGrayImages=true \ - -dDownsampleColorImages=true \ - -dMonoImageDownsampleThreshold=2.0 \ - -dGrayImageDownsampleThreshold=1.5 \ - -dColorImageDownsampleThreshold=1.5 \ - -dMonoImageResolution=600 \ - -dGrayImageResolution=600 \ - -dColorImageResolution=600 \ - -dAutoFilterMonoImages=false \ - -dMonoImageFilter=/FlateEncode \ - -dAutoFilterGrayImages=true \ - -dAutoFilterColorImages=true" -fi - -if [ $rot == 1 ] -then - options="$options -dAutoRotatePages=/PageByPage" -fi - -if [ $eps == 1 ] -then - options="$options -dEPSCrop" -fi - -set -x - -if [ $a4 == 1 ] -then - # Resize from A4 to letter size - psresize -Pa4 -pletter "$ifilename" myps2pdf.temp.ps - ifilename=myps2pdf.temp.ps -fi - -gs -q -dSAFER -dNOPAUSE -dBATCH \ - -sDEVICE=pdfwrite -sPAPERSIZE=letter -sOutputFile=myps2pdf.temp.pdf \ - -dCompatibilityLevel=1.3 \ - $options \ - -dMaxSubsetPct=100 \ - -dSubsetFonts=true \ - -dEmbedAllFonts=true \ - -dColorConversionStrategy=/LeaveColorUnchanged \ - -dDoThumbnails=true \ - -dPreserveEPSInfo=true \ - -c .setpdfwrite -f "$ifilename" - -if [ $do_opt == 1 ] -then - pdfopt myps2pdf.temp.pdf $ofilename -else - mv myps2pdf.temp.pdf $ofilename -fi -rm -f myps2pdf.temp.pdf myps2pdf.temp.ps diff --git a/gem/t1.lua b/gem/t1.lua deleted file mode 100644 index 0c054c9..0000000 --- a/gem/t1.lua +++ /dev/null @@ -1,25 +0,0 @@ -source = {} -sink = {} -pump = {} -filter = {} - --- source.chain -dofile("ex6.lua") - --- source.file -dofile("ex5.lua") - --- normalize -require"gem" -eol = gem.eol -dofile("ex2.lua") - --- sink.file -require"ltn12" -sink.file = ltn12.sink.file - --- pump.all -dofile("ex10.lua") - --- run test -dofile("ex1.lua") diff --git a/gem/t1lf.txt b/gem/t1lf.txt deleted file mode 100644 index 8cddd1b..0000000 --- a/gem/t1lf.txt +++ /dev/null @@ -1,5 +0,0 @@ -this is a test file -it should have been saved as lf eol -but t1.lua will convert it to crlf eol -otherwise it is broken! - diff --git a/gem/t2.lua b/gem/t2.lua deleted file mode 100644 index a81ed73..0000000 --- a/gem/t2.lua +++ /dev/null @@ -1,36 +0,0 @@ -source = {} -sink = {} -pump = {} -filter = {} - --- filter.chain -dofile("ex3.lua") - --- normalize -require"gem" -eol = gem.eol -dofile("ex2.lua") - --- encode -require"mime" -encode = mime.encode - --- wrap -wrap = mime.wrap - --- source.chain -dofile("ex6.lua") - --- source.file -dofile("ex5.lua") - --- sink.file -require"ltn12" -sink.file = ltn12.sink.file - --- pump.all -dofile("ex10.lua") - --- run test -CRLF = "\013\010" -dofile("ex4.lua") diff --git a/gem/t2.txt b/gem/t2.txt deleted file mode 100644 index f484fe8..0000000 --- a/gem/t2.txt +++ /dev/null @@ -1,4 +0,0 @@ -esse é um texto com acentos -quoted-printable tem que quebrar linhas longas, com mais que 76 linhas de texto -fora que as quebras de linhas têm que ser normalizadas -vamos ver o que dá isso aqui diff --git a/gem/t2gt.qp b/gem/t2gt.qp deleted file mode 100644 index 355a845..0000000 --- a/gem/t2gt.qp +++ /dev/null @@ -1,5 +0,0 @@ -esse =E9 um texto com acentos -quoted-printable tem que quebrar linhas longas, com mais que 76 linhas de t= -exto -fora que as quebras de linhas t=EAm que ser normalizadas -vamos ver o que d=E1 isso aqui diff --git a/gem/t3.lua b/gem/t3.lua deleted file mode 100644 index 4bb98ba..0000000 --- a/gem/t3.lua +++ /dev/null @@ -1,25 +0,0 @@ -source = {} -sink = {} -pump = {} -filter = {} - --- source.file -dofile("ex5.lua") - --- sink.table -dofile("ex7.lua") - --- sink.chain -require"ltn12" -sink.chain = ltn12.sink.chain - --- normalize -require"gem" -eol = gem.eol -dofile("ex2.lua") - --- pump.all -dofile("ex10.lua") - --- run test -dofile("ex8.lua") diff --git a/gem/t4.lua b/gem/t4.lua deleted file mode 100644 index 8b8071c..0000000 --- a/gem/t4.lua +++ /dev/null @@ -1,10 +0,0 @@ -source = {} -sink = {} -pump = {} -filter = {} - --- source.file -dofile("ex5.lua") - --- run test -dofile("ex9.lua") diff --git a/gem/t5.lua b/gem/t5.lua deleted file mode 100644 index 7c569ea..0000000 --- a/gem/t5.lua +++ /dev/null @@ -1,30 +0,0 @@ -source = {} -sink = {} -pump = {} -filter = {} - --- source.chain -dofile("ex6.lua") - --- source.file -dofile("ex5.lua") - --- encode -require"mime" -encode = mime.encode - --- sink.chain -require"ltn12" -sink.chain = ltn12.sink.chain - --- wrap -wrap = mime.wrap - --- sink.file -sink.file = ltn12.sink.file - --- pump.all -dofile("ex10.lua") - --- run test -dofile("ex11.lua") diff --git a/gem/test.lua b/gem/test.lua deleted file mode 100644 index a937b9a..0000000 --- a/gem/test.lua +++ /dev/null @@ -1,46 +0,0 @@ -function readfile(n) - local f = io.open(n, "rb") - local s = f:read("*a") - f:close() - return s -end - -lf = readfile("t1lf.txt") -os.remove("t1crlf.txt") -os.execute("lua t1.lua < t1lf.txt > t1crlf.txt") -crlf = readfile("t1crlf.txt") -assert(crlf == string.gsub(lf, "\010", "\013\010"), "broken") - -gt = readfile("t2gt.qp") -os.remove("t2.qp") -os.execute("lua t2.lua < t2.txt > t2.qp") -t2 = readfile("t2.qp") -assert(gt == t2, "broken") - -os.remove("t1crlf.txt") -os.execute("lua t3.lua < t1lf.txt > t1crlf.txt") -crlf = readfile("t1crlf.txt") -assert(crlf == string.gsub(lf, "\010", "\013\010"), "broken") - -t = readfile("test.lua") -os.execute("lua t4.lua < test.lua > t") -t2 = readfile("t") -assert(t == t2, "broken") - -os.remove("output.b64") -gt = readfile("gt.b64") -os.execute("lua t5.lua") -t5 = readfile("output.b64") -assert(gt == t5, "failed") - -print("1 2 5 6 10 passed") -print("2 3 4 5 6 10 passed") -print("2 5 6 7 8 10 passed") -print("5 9 passed") -print("5 6 10 11 passed") - -os.remove("t") -os.remove("t2.qp") -os.remove("t1crlf.txt") -os.remove("t11.b64") -os.remove("output.b64") From 86de838eb5ed49711be8d62e01255cc2ccd3342e Mon Sep 17 00:00:00 2001 From: Thijs Schreijer Date: Wed, 23 Mar 2022 16:05:11 +0100 Subject: [PATCH 4/7] cleanup; move ./etc into ./samples and mark 'unsupported' --- .luacheckrc | 2 - etc/README | 89 ------------------------------ luasocket-scm-3.rockspec | 1 - makefile.dist | 28 ++++------ samples/README | 90 +++++++++++++++++++++++++++++-- {etc => samples}/b64.lua | 0 {etc => samples}/check-links.lua | 0 {etc => samples}/check-memory.lua | 0 {etc => samples}/cookie.lua | 0 {etc => samples}/dict.lua | 0 {etc => samples}/dispatch.lua | 0 {etc => samples}/eol.lua | 0 {etc => samples}/forward.lua | 0 {etc => samples}/get.lua | 0 {etc => samples}/links | 0 {etc => samples}/lp.lua | 0 {etc => samples}/qp.lua | 0 {etc => samples}/tftp.lua | 0 18 files changed, 98 insertions(+), 112 deletions(-) delete mode 100644 etc/README rename {etc => samples}/b64.lua (100%) rename {etc => samples}/check-links.lua (100%) rename {etc => samples}/check-memory.lua (100%) rename {etc => samples}/cookie.lua (100%) rename {etc => samples}/dict.lua (100%) rename {etc => samples}/dispatch.lua (100%) rename {etc => samples}/eol.lua (100%) rename {etc => samples}/forward.lua (100%) rename {etc => samples}/get.lua (100%) rename {etc => samples}/links (100%) rename {etc => samples}/lp.lua (100%) rename {etc => samples}/qp.lua (100%) rename {etc => samples}/tftp.lua (100%) diff --git a/.luacheckrc b/.luacheckrc index 8b25dd7..a3b4f63 100644 --- a/.luacheckrc +++ b/.luacheckrc @@ -15,8 +15,6 @@ include_files = { } exclude_files = { - "etc/*.lua", - "etc/**/*.lua", "test/*.lua", "test/**/*.lua", "samples/*.lua", diff --git a/etc/README b/etc/README deleted file mode 100644 index cfd3e37..0000000 --- a/etc/README +++ /dev/null @@ -1,89 +0,0 @@ -This directory contains code that is more useful than the -samples. This code *is* supported. - - tftp.lua -- Trivial FTP client - -This module implements file retrieval by the TFTP protocol. -Its main use was to test the UDP code, but since someone -found it usefull, I turned it into a module that is almost -official (no uploads, yet). - - dict.lua -- Dict client - -The dict.lua module started with a cool simple client -for the DICT protocol, written by Luiz Henrique Figueiredo. -This new version has been converted into a library, similar -to the HTTP and FTP libraries, that can be used from within -any luasocket application. Take a look on the source code -and you will be able to figure out how to use it. - - lp.lua -- LPD client library - -The lp.lua module implements the client part of the Line -Printer Daemon protocol, used to print files on Unix -machines. It is courtesy of David Burgess! See the source -code and the lpr.lua in the examples directory. - - b64.lua - qp.lua - eol.lua - -These are tiny programs that perform Base64, -Quoted-Printable and end-of-line marker conversions. - - get.lua -- file retriever - -This little program is a client that uses the FTP and -HTTP code to implement a command line file graber. Just -run - - lua get.lua [] - -to download a remote file (either ftp:// or http://) to -the specified local file. The program also prints the -download throughput, elapsed time, bytes already downloaded -etc during download. - - check-memory.lua -- checks memory consumption - -This is just to see how much memory each module uses. - - dispatch.lua -- coroutine based dispatcher - -This is a first try at a coroutine based non-blocking -dispatcher for LuaSocket. Take a look at 'check-links.lua' -and at 'forward.lua' to see how to use it. - - check-links.lua -- HTML link checker program - -This little program scans a HTML file and checks for broken -links. It is similar to check-links.pl by Jamie Zawinski, -but uses all facilities of the LuaSocket library and the Lua -language. It has not been thoroughly tested, but it should -work. Just run - - lua check-links.lua [-n] {} > output - -and open the result to see a list of broken links. Make sure -you check the '-n' switch. It runs in non-blocking mode, -using coroutines, and is MUCH faster! - - forward.lua -- coroutine based forward server - -This is a forward server that can accept several connections -and transfers simultaneously using non-blocking I/O and the -coroutine-based dispatcher. You can run, for example - - lua forward.lua 8080:proxy.com:3128 - -to redirect all local conections to port 8080 to the host -'proxy.com' at port 3128. - - unix.c and unix.h - -This is an implementation of Unix local domain sockets and -demonstrates how to extend LuaSocket with a new type of -transport. It has been tested on Linux and on Mac OS X. - -Good luck, -Diego. diff --git a/luasocket-scm-3.rockspec b/luasocket-scm-3.rockspec index 71f335c..f3d24e3 100644 --- a/luasocket-scm-3.rockspec +++ b/luasocket-scm-3.rockspec @@ -129,6 +129,5 @@ build = { copy_directories = { "docs" , "samples" - , "etc" , "test" } } diff --git a/makefile.dist b/makefile.dist index a27ba57..5ef44d3 100644 --- a/makefile.dist +++ b/makefile.dist @@ -22,20 +22,17 @@ SAMPLES = \ samples/lpr.lua \ samples/talker.lua \ samples/tinyirc.lua - -ETC = \ - etc/README \ - etc/b64.lua \ - etc/check-links.lua \ - etc/check-memory.lua \ - etc/dict.lua \ - etc/dispatch.lua \ - etc/eol.lua \ - etc/forward.lua \ - etc/get.lua \ - etc/lp.lua \ - etc/qp.lua \ - etc/tftp.lua + samples/b64.lua \ + samples/check-links.lua \ + samples/check-memory.lua \ + samples/dict.lua \ + samples/dispatch.lua \ + samples/eol.lua \ + samples/forward.lua \ + samples/get.lua \ + samples/lp.lua \ + samples/qp.lua \ + samples/tftp.lua SRC = \ src/makefile \ @@ -117,9 +114,6 @@ dist: cp -vf README.md $(DIST) cp -vf $(MAKE) $(DIST) - mkdir -p $(DIST)/etc - cp -vf $(ETC) $(DIST)/etc - mkdir -p $(DIST)/src cp -vf $(SRC) $(DIST)/src diff --git a/samples/README b/samples/README index e63a6f5..4ee06b6 100644 --- a/samples/README +++ b/samples/README @@ -1,11 +1,95 @@ This directory contains some sample programs using LuaSocket. This code is not supported. + tftp.lua -- Trivial FTP client + +This module implements file retrieval by the TFTP protocol. +Its main use was to test the UDP code, but since someone +found it usefull, I turned it into a module that is almost +official (no uploads, yet). + + dict.lua -- Dict client + +The dict.lua module started with a cool simple client +for the DICT protocol, written by Luiz Henrique Figueiredo. +This new version has been converted into a library, similar +to the HTTP and FTP libraries, that can be used from within +any luasocket application. Take a look on the source code +and you will be able to figure out how to use it. + + lp.lua -- LPD client library + +The lp.lua module implements the client part of the Line +Printer Daemon protocol, used to print files on Unix +machines. It is courtesy of David Burgess! See the source +code and the lpr.lua in the examples directory. + + b64.lua + qp.lua + eol.lua + +These are tiny programs that perform Base64, +Quoted-Printable and end-of-line marker conversions. + + get.lua -- file retriever + +This little program is a client that uses the FTP and +HTTP code to implement a command line file graber. Just +run + + lua get.lua [] + +to download a remote file (either ftp:// or http://) to +the specified local file. The program also prints the +download throughput, elapsed time, bytes already downloaded +etc during download. + + check-memory.lua -- checks memory consumption + +This is just to see how much memory each module uses. + + dispatch.lua -- coroutine based dispatcher + +This is a first try at a coroutine based non-blocking +dispatcher for LuaSocket. Take a look at 'check-links.lua' +and at 'forward.lua' to see how to use it. + + check-links.lua -- HTML link checker program + +This little program scans a HTML file and checks for broken +links. It is similar to check-links.pl by Jamie Zawinski, +but uses all facilities of the LuaSocket library and the Lua +language. It has not been thoroughly tested, but it should +work. Just run + + lua check-links.lua [-n] {} > output + +and open the result to see a list of broken links. Make sure +you check the '-n' switch. It runs in non-blocking mode, +using coroutines, and is MUCH faster! + + forward.lua -- coroutine based forward server + +This is a forward server that can accept several connections +and transfers simultaneously using non-blocking I/O and the +coroutine-based dispatcher. You can run, for example + + lua forward.lua 8080:proxy.com:3128 + +to redirect all local conections to port 8080 to the host +'proxy.com' at port 3128. + + unix.c and unix.h + +This is an implementation of Unix local domain sockets and +demonstrates how to extend LuaSocket with a new type of +transport. It has been tested on Linux and on Mac OS X. + listener.lua -- socket to stdout talker.lua -- stdin to socket listener.lua and talker.lua are about the simplest -applications you can write using LuaSocket. Run +applications you can write using LuaSocket. Run 'lua listener.lua' and 'lua talker.lua' @@ -17,13 +101,13 @@ be printed by listen.lua. This is a cool program written by David Burgess to print files using the Line Printer Daemon protocol, widely used in Unix machines. It uses the lp.lua implementation, in the -etc directory. Just run 'lua lpr.lua +samples directory. Just run 'lua lpr.lua queue=' and the file will print! cddb.lua -- CDDB client This is the first try on a simple CDDB client. Not really -useful, but one day it might become a module. +useful, but one day it might become a module. daytimeclnt.lua -- day time client diff --git a/etc/b64.lua b/samples/b64.lua similarity index 100% rename from etc/b64.lua rename to samples/b64.lua diff --git a/etc/check-links.lua b/samples/check-links.lua similarity index 100% rename from etc/check-links.lua rename to samples/check-links.lua diff --git a/etc/check-memory.lua b/samples/check-memory.lua similarity index 100% rename from etc/check-memory.lua rename to samples/check-memory.lua diff --git a/etc/cookie.lua b/samples/cookie.lua similarity index 100% rename from etc/cookie.lua rename to samples/cookie.lua diff --git a/etc/dict.lua b/samples/dict.lua similarity index 100% rename from etc/dict.lua rename to samples/dict.lua diff --git a/etc/dispatch.lua b/samples/dispatch.lua similarity index 100% rename from etc/dispatch.lua rename to samples/dispatch.lua diff --git a/etc/eol.lua b/samples/eol.lua similarity index 100% rename from etc/eol.lua rename to samples/eol.lua diff --git a/etc/forward.lua b/samples/forward.lua similarity index 100% rename from etc/forward.lua rename to samples/forward.lua diff --git a/etc/get.lua b/samples/get.lua similarity index 100% rename from etc/get.lua rename to samples/get.lua diff --git a/etc/links b/samples/links similarity index 100% rename from etc/links rename to samples/links diff --git a/etc/lp.lua b/samples/lp.lua similarity index 100% rename from etc/lp.lua rename to samples/lp.lua diff --git a/etc/qp.lua b/samples/qp.lua similarity index 100% rename from etc/qp.lua rename to samples/qp.lua diff --git a/etc/tftp.lua b/samples/tftp.lua similarity index 100% rename from etc/tftp.lua rename to samples/tftp.lua From 3adf252b45401b4b97e63668c6ee530e7b3936ad Mon Sep 17 00:00:00 2001 From: Thijs Schreijer Date: Wed, 23 Mar 2022 16:15:52 +0100 Subject: [PATCH 5/7] cleanup; move FIX, TODO, WISH into TODO.md --- FIX | 28 ------------ TODO | 81 ---------------------------------- TODO.md | 135 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ WISH | 22 --------- 4 files changed, 135 insertions(+), 131 deletions(-) delete mode 100644 FIX delete mode 100644 TODO create mode 100644 TODO.md delete mode 100644 WISH diff --git a/FIX b/FIX deleted file mode 100644 index 40f30a1..0000000 --- a/FIX +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - -http was preserving old host header during redirects -fix smtp.send hang on source error -add create field to FTP and SMTP and fix HTTP ugliness -clean timeout argument to open functions in SMTP, HTTP and FTP -eliminate globals from namespaces created by module(). -url.absolute was not working when base_url was already parsed -http.request was redirecting even when the location header was empty -tcp{client}:shutdown() was checking for group instead of class. -tcp{client}:send() now returns i+sent-1... -get rid of a = socket.try() in the manual, except for protected cases. replace it with assert. -get rid of "base." kludge in package.loaded -check all "require("http")" etc in the manual. -make sure sock_gethostname.* only return success if the hp is not null! -change 'l' prefix in C libraries to 'c' to avoid clash with LHF libraries - don't forget the declarations in luasocket.h and mime.h!!! -setpeername was using udp{unconnected} -fixed a bug in http.lua that caused some requests to fail (Florian Berger) -fixed a bug in select.c that prevented sockets with descriptor 0 from working (Renato Maia) -fixed a "bug" that caused dns.toip to crash under uLinux -fixed a "bug" that caused a crash in gethostbyname under VMS -DEBUG and VERSION became _DEBUG and _VERSION -send returns the right value if input is "". Alexander Marinov diff --git a/TODO b/TODO deleted file mode 100644 index a838fc0..0000000 --- a/TODO +++ /dev/null @@ -1,81 +0,0 @@ -- bizarre default values for getnameinfo should throw error instead! - -> It's just too bad it can't talk to gmail - -> reason 1: they absolutely want TLS -> reason 2: unlike all the other SMTP implementations, they -> don't -> tolerate missing < > around adresses - -- document the new bind and connect behavior. -- shouldn't we instead make the code compatible to Lua 5.2 - without any compat stuff, and use a compatibility layer to - make it work on 5.1? -- add what's new to manual -- should there be an equivalent to tohostname for IPv6? -- should we add service name resolution as well to getaddrinfo? -- Maybe the sockaddr to presentation conversion should be done with getnameinfo()? - -- add http POST sample to manual - people keep asking stupid questions -- documentation of dirty/getfd/setfd is problematic because of portability - same for unix and serial. - what to do about this? add a stronger disclaimer? -- fix makefile with decent defaults? - -Done: - -- added IPv6 support to getsockname -- simplified getpeername implementation -- added family to return of getsockname and getpeername - and added modification to the manual to describe - -- connect and bind try all adresses returned by getaddrinfo -- document headers.lua? -- update copyright date everywhere? -- remove RCSID from files? -- move version to 2.1 rather than 2.1.1? -- fixed url package to support ipv6 hosts -- changed domain to family -- implement getfamily methods. - -- remove references to Lua 5.0 from documentation, add 5.2? -- update lua and luasocket version in samples in documentation -- document ipv5_v6only default option being set? -- document tcp6 and udp6 -- document dns.getaddrinfo -- documented zero-sized datagram change? - no. -- document unix socket and serial socket? add raw support? - no. -- document getoption -- merge luaL_typeerror into auxiliar to avoid using luaL prefix? - - - - - - - - - - -replace \r\n with \0xD\0xA in everything -New mime support - -ftp send should return server replies? -make sure there are no object files in the distribution tarball -http handling of 100-continue, see DB patch -DB ftp.lua bug. -test unix.c to return just a function and works with require"unix" -get rid of setmetatable(, nil) since packages don't need this anymore in 5.1 -compat-5.1 novo -ajeitar pra lua-5.1 - -adicionar exemplos de expansão: pipe, local, named pipe -testar os options! - - -- Thread-unsafe functions to protect - gethostbyname(), gethostbyaddr(), gethostent(), -inet_ntoa(), strerror(), - diff --git a/TODO.md b/TODO.md new file mode 100644 index 0000000..d265694 --- /dev/null +++ b/TODO.md @@ -0,0 +1,135 @@ +## FIX + +http was preserving old host header during redirects +fix smtp.send hang on source error +add create field to FTP and SMTP and fix HTTP ugliness +clean timeout argument to open functions in SMTP, HTTP and FTP +eliminate globals from namespaces created by module(). +url.absolute was not working when base_url was already parsed +http.request was redirecting even when the location header was empty +tcp{client}:shutdown() was checking for group instead of class. +tcp{client}:send() now returns i+sent-1... +get rid of a = socket.try() in the manual, except for protected cases. replace it with assert. +get rid of "base." kludge in package.loaded +check all "require("http")" etc in the manual. +make sure sock_gethostname.* only return success if the hp is not null! +change 'l' prefix in C libraries to 'c' to avoid clash with LHF libraries + don't forget the declarations in luasocket.h and mime.h!!! +setpeername was using udp{unconnected} +fixed a bug in http.lua that caused some requests to fail (Florian Berger) +fixed a bug in select.c that prevented sockets with descriptor 0 from working (Renato Maia) +fixed a "bug" that caused dns.toip to crash under uLinux +fixed a "bug" that caused a crash in gethostbyname under VMS +DEBUG and VERSION became _DEBUG and _VERSION +send returns the right value if input is "". Alexander Marinov + + +## WISH + +... as an l-value to get all results of a function call? +at least ...[i] and #... +extend to full tuples? + +__and __or __not metamethods + +lua_tostring, lua_tonumber, lua_touseradta etc push values in stack +__tostring,__tonumber, __touserdata metamethods are checked +and expected to push an object of correct type on stack + +lua_rawtostring, lua_rawtonumber, lua_rawtouserdata don't +push anything on stack, return data of appropriate type, +skip metamethods and throw error if object not of exact type + +package.findfile exported +module not polluting the global namespace + +coxpcall with a coroutine pool for efficiency (reusing coroutines) + +exception mechanism formalized? just like the package system was. + +a nice bitlib in the core + + +## TODO + +- bizarre default values for getnameinfo should throw error instead! + +> It's just too bad it can't talk to gmail - +> reason 1: they absolutely want TLS +> reason 2: unlike all the other SMTP implementations, they +> don't +> tolerate missing < > around adresses + +- document the new bind and connect behavior. +- shouldn't we instead make the code compatible to Lua 5.2 + without any compat stuff, and use a compatibility layer to + make it work on 5.1? +- add what's new to manual +- should there be an equivalent to tohostname for IPv6? +- should we add service name resolution as well to getaddrinfo? +- Maybe the sockaddr to presentation conversion should be done with getnameinfo()? + +- add http POST sample to manual + people keep asking stupid questions +- documentation of dirty/getfd/setfd is problematic because of portability + same for unix and serial. + what to do about this? add a stronger disclaimer? +- fix makefile with decent defaults? + +## Done: + +- added IPv6 support to getsockname +- simplified getpeername implementation +- added family to return of getsockname and getpeername + and added modification to the manual to describe + +- connect and bind try all adresses returned by getaddrinfo +- document headers.lua? +- update copyright date everywhere? +- remove RCSID from files? +- move version to 2.1 rather than 2.1.1? +- fixed url package to support ipv6 hosts +- changed domain to family +- implement getfamily methods. + +- remove references to Lua 5.0 from documentation, add 5.2? +- update lua and luasocket version in samples in documentation +- document ipv5_v6only default option being set? +- document tcp6 and udp6 +- document dns.getaddrinfo +- documented zero-sized datagram change? + no. +- document unix socket and serial socket? add raw support? + no. +- document getoption +- merge luaL_typeerror into auxiliar to avoid using luaL prefix? + + + + + + + + + + +replace \r\n with \0xD\0xA in everything +New mime support + +ftp send should return server replies? +make sure there are no object files in the distribution tarball +http handling of 100-continue, see DB patch +DB ftp.lua bug. +test unix.c to return just a function and works with require"unix" +get rid of setmetatable(, nil) since packages don't need this anymore in 5.1 +compat-5.1 novo +ajeitar pra lua-5.1 + +adicionar exemplos de expans�o: pipe, local, named pipe +testar os options! + + +- Thread-unsafe functions to protect + gethostbyname(), gethostbyaddr(), gethostent(), +inet_ntoa(), strerror(), + diff --git a/WISH b/WISH deleted file mode 100644 index e7e9c07..0000000 --- a/WISH +++ /dev/null @@ -1,22 +0,0 @@ -... as an l-value to get all results of a function call? -at least ...[i] and #... -extend to full tuples? - -__and __or __not metamethods - -lua_tostring, lua_tonumber, lua_touseradta etc push values in stack -__tostring,__tonumber, __touserdata metamethods are checked -and expected to push an object of correct type on stack - -lua_rawtostring, lua_rawtonumber, lua_rawtouserdata don't -push anything on stack, return data of appropriate type, -skip metamethods and throw error if object not of exact type - -package.findfile exported -module not polluting the global namespace - -coxpcall with a coroutine pool for efficiency (reusing coroutines) - -exception mechanism formalized? just like the package system was. - -a nice bitlib in the core From db2f1c9598c63a721fad4b8ae0e0121eccc86248 Mon Sep 17 00:00:00 2001 From: Thijs Schreijer Date: Tue, 29 Mar 2022 14:09:10 +0200 Subject: [PATCH 6/7] chore(ltn) update file contents from wiki to markdown --- ltn012.wiki | 205 ++++++++++++++++++++++++++-------------------------- ltn013.wiki | 127 ++++++++++++++++---------------- 2 files changed, 163 insertions(+), 169 deletions(-) diff --git a/ltn012.wiki b/ltn012.wiki index 96b13ae..fa26b4a 100644 --- a/ltn012.wiki +++ b/ltn012.wiki @@ -1,51 +1,48 @@ -===Filters, sources and sinks: design, motivation and examples=== -==or Functional programming for the rest of us== +# Filters, sources and sinks: design, motivation and examples +### or Functional programming for the rest of us by DiegoNehab -{{{ +## Abstract -}}} +Certain operations can be implemented in the form of filters. A filter is a function that processes data received in consecutive function calls, returning partial results chunk by chunk. Examples of operations that can be implemented as filters include the end-of-line normalization for text, Base64 and Quoted-Printable transfer content encodings, the breaking of text into lines, SMTP byte stuffing, and there are many others. Filters become even more powerful when we allow them to be chained together to create composite filters. Filters can be seen as middle nodes in a chain of data transformations. Sources an sinks are the corresponding end points of these chains. A source is a function that produces data, chunk by chunk, and a sink is a function that takes data, chunk by chunk. In this technical note, we define an elegant interface for filters, sources, sinks and chaining. We evolve our interface progressively, until we reach a high degree of generality. We discuss difficulties that arise during the implementation of this interface and we provide solutions and examples. -===Abstract=== -Certain operations can be implemented in the form of filters. A filter is a function that processes data received in consecutive function calls, returning partial results chunk by chunk. Examples of operations that can be implemented as filters include the end-of-line normalization for text, Base64 and Quoted-Printable transfer content encodings, the breaking of text into lines, SMTP byte stuffing, and there are many others. Filters become even more powerful when we allow them to be chained together to create composite filters. Filters can be seen as middle nodes in a chain of data transformations. Sources an sinks are the corresponding end points of these chains. A source is a function that produces data, chunk by chunk, and a sink is a function that takes data, chunk by chunk. In this technical note, we define an elegant interface for filters, sources, sinks and chaining. We evolve our interface progressively, until we reach a high degree of generality. We discuss difficulties that arise during the implementation of this interface and we provide solutions and examples. +## Introduction -===Introduction=== +Applications sometimes have too much information to process to fit in memory and are thus forced to process data in smaller parts. Even when there is enough memory, processing all the data atomically may take long enough to frustrate a user that wants to interact with the application. Furthermore, complex transformations can often be defined as series of simpler operations. Several different complex transformations might share the same simpler operations, so that an uniform interface to combine them is desirable. The following concepts constitute our solution to these problems. -Applications sometimes have too much information to process to fit in memory and are thus forced to process data in smaller parts. Even when there is enough memory, processing all the data atomically may take long enough to frustrate a user that wants to interact with the application. Furthermore, complex transformations can often be defined as series of simpler operations. Several different complex transformations might share the same simpler operations, so that an uniform interface to combine them is desirable. The following concepts constitute our solution to these problems. +"Filters" are functions that accept successive chunks of input, and produce successive chunks of output. Furthermore, the result of concatenating all the output data is the same as the result of applying the filter over the concatenation of the input data. As a consequence, boundaries are irrelevant: filters have to handle input data split arbitrarily by the user. -''Filters'' are functions that accept successive chunks of input, and produce successive chunks of output. Furthermore, the result of concatenating all the output data is the same as the result of applying the filter over the concatenation of the input data. As a consequence, boundaries are irrelevant: filters have to handle input data split arbitrarily by the user. +A "chain" is a function that combines the effect of two (or more) other functions, but whose interface is indistinguishable from the interface of one of its components. Thus, a chained filter can be used wherever an atomic filter can be used. However, its effect on data is the combined effect of its component filters. Note that, as a consequence, chains can be chained themselves to create arbitrarily complex operations that can be used just like atomic operations. -A ''chain'' is a function that combines the effect of two (or more) other functions, but whose interface is indistinguishable from the interface of one of its components. Thus, a chained filter can be used wherever an atomic filter can be used. However, its effect on data is the combined effect of its component filters. Note that, as a consequence, chains can be chained themselves to create arbitrarily complex operations that can be used just like atomic operations. +Filters can be seen as internal nodes in a network through which data flows, potentially being transformed along its way. Chains connect these nodes together. To complete the picture, we need "sources" and "sinks" as initial and final nodes of the network, respectively. Less abstractly, a source is a function that produces new data every time it is called. On the other hand, sinks are functions that give a final destination to the data they receive. Naturally, sources and sinks can be chained with filters. -Filters can be seen as internal nodes in a network through which data flows, potentially being transformed along its way. Chains connect these nodes together. To complete the picture, we need ''sources'' and ''sinks'' as initial and final nodes of the network, respectively. Less abstractly, a source is a function that produces new data every time it is called. On the other hand, sinks are functions that give a final destination to the data they receive. Naturally, sources and sinks can be chained with filters. +Finally, filters, chains, sources, and sinks are all passive entities: they need to be repeatedly called in order for something to happen. "Pumps" provide the driving force that pushes data through the network, from a source to a sink. -Finally, filters, chains, sources, and sinks are all passive entities: they need to be repeatedly called in order for something to happen. ''Pumps'' provide the driving force that pushes data through the network, from a source to a sink. + Hopefully, these concepts will become clear with examples. In the following sections, we start with simplified interfaces, which we improve several times until we can find no obvious shortcomings. The evolution we present is not contrived: it follows the steps we followed ourselves as we consolidated our understanding of these concepts. - Hopefully, these concepts will become clear with examples. In the following sections, we start with simplified interfaces, which we improve several times until we can find no obvious shortcomings. The evolution we present is not contrived: it follows the steps we followed ourselves as we consolidated our understanding of these concepts. +### A concrete example -== A concrete example == - -Some data transformations are easier to implement as filters than others. Examples of operations that can be implemented as filters include the end-of-line normalization for text, the Base64 and Quoted-Printable transfer content encodings, the breaking of text into lines, SMTP byte stuffing, and many others. Let's use the end-of-line normalization as an example to define our initial filter interface. We later discuss why the implementation might not be trivial. +Some data transformations are easier to implement as filters than others. Examples of operations that can be implemented as filters include the end-of-line normalization for text, the Base64 and Quoted-Printable transfer content encodings, the breaking of text into lines, SMTP byte stuffing, and many others. Let's use the end-of-line normalization as an example to define our initial filter interface. We later discuss why the implementation might not be trivial. Assume we are given text in an unknown end-of-line convention (including possibly mixed conventions) out of the commonly found Unix (LF), Mac OS (CR), and DOS (CRLF) conventions. We would like to be able to write code like the following: - {{{ +```lua input = source.chain(source.file(io.stdin), normalize("\r\n")) output = sink.file(io.stdout) pump(input, output) -}}} +``` -This program should read data from the standard input stream and normalize the end-of-line markers to the canonic CRLF marker defined by the MIME standard, finally sending the results to the standard output stream. For that, we use a ''file source'' to produce data from standard input, and chain it with a filter that normalizes the data. The pump then repeatedly gets data from the source, and moves it to the ''file sink'' that sends it to standard output. +This program should read data from the standard input stream and normalize the end-of-line markers to the canonic CRLF marker defined by the MIME standard, finally sending the results to the standard output stream. For that, we use a "file source" to produce data from standard input, and chain it with a filter that normalizes the data. The pump then repeatedly gets data from the source, and moves it to the "file sink" that sends it to standard output. -To make the discussion even more concrete, we start by discussing the implementation of the normalization filter. The {{normalize}} ''factory'' is a function that creates such a filter. Our initial filter interface is as follows: the filter receives a chunk of input data, and returns a chunk of processed data. When there is no more input data, the user notifies the filter by invoking it with a {{nil}} chunk. The filter then returns the final chunk of processed data. +To make the discussion even more concrete, we start by discussing the implementation of the normalization filter. The `normalize` "factory" is a function that creates such a filter. Our initial filter interface is as follows: the filter receives a chunk of input data, and returns a chunk of processed data. When there is no more input data, the user notifies the filter by invoking it with a `nil` chunk. The filter then returns the final chunk of processed data. -Although the interface is extremely simple, the implementation doesn't seem so obvious. Any filter respecting this interface needs to keep some kind of context between calls. This is because chunks can be broken between the CR and LF characters marking the end of a line. This need for context storage is what motivates the use of factories: each time the factory is called, it returns a filter with its own context so that we can have several independent filters being used at the same time. For the normalization filter, we know that the obvious solution (i.e. concatenating all the input into the context before producing any output) is not good enough, so we will have to find another way. +Although the interface is extremely simple, the implementation doesn't seem so obvious. Any filter respecting this interface needs to keep some kind of context between calls. This is because chunks can be broken between the CR and LF characters marking the end of a line. This need for context storage is what motivates the use of factories: each time the factory is called, it returns a filter with its own context so that we can have several independent filters being used at the same time. For the normalization filter, we know that the obvious solution (i.e. concatenating all the input into the context before producing any output) is not good enough, so we will have to find another way. We will break the implementation in two parts: a low-level filter, and a factory of high-level filters. The low-level filter will be implemented in C and will not carry any context between function calls. The high-level filter factory, implemented in Lua, will create and return a high-level filter that keeps whatever context the low-level filter needs, but isolates the user from its internal details. That way, we take advantage of C's efficiency to perform the dirty work, and take advantage of Lua's simplicity for the bookkeeping. -==The Lua part of the implementation== +### The Lua part of the implementation Below is the implementation of the factory of high-level end-of-line normalization filters: - {{{ +```lua function filter.cycle(low, ctx, extra) return function(chunk) local ret @@ -57,18 +54,18 @@ end function normalize(marker) return cycle(eol, 0, marker) end -}}} +``` -The {{normalize}} factory simply calls a more generic factory, the {{cycle}} factory. This factory receives a low-level filter, an initial context and some extra value and returns the corresponding high-level filter. Each time the high level filer is called with a new chunk, it calls the low-level filter passing the previous context, the new chunk and the extra argument. The low-level filter produces the chunk of processed data and a new context. Finally, the high-level filter updates its internal context and returns the processed chunk of data to the user. It is the low-level filter that does all the work. Notice that this implementation takes advantage of the Lua 5.0 lexical scoping rules to store the context locally, between function calls. +The `normalize` factory simply calls a more generic factory, the `cycle` factory. This factory receives a low-level filter, an initial context and some extra value and returns the corresponding high-level filter. Each time the high level filer is called with a new chunk, it calls the low-level filter passing the previous context, the new chunk and the extra argument. The low-level filter produces the chunk of processed data and a new context. Finally, the high-level filter updates its internal context and returns the processed chunk of data to the user. It is the low-level filter that does all the work. Notice that this implementation takes advantage of the Lua 5.0 lexical scoping rules to store the context locally, between function calls. Moving to the low-level filter, we notice there is no perfect solution to the end-of-line marker normalization problem itself. The difficulty comes from an inherent ambiguity on the definition of empty lines within mixed input. However, the following solution works well for any consistent input, as well as for non-empty lines in mixed input. It also does a reasonable job with empty lines and serves as a good example of how to implement a low-level filter. -Here is what we do: CR and LF are considered candidates for line break. We issue ''one'' end-of-line line marker if one of the candidates is seen alone, or followed by a ''different'' candidate. That is, CR CR and LF LF issue two end of line markers each, but CR LF and LF CR issue only one marker. This idea takes care of Mac OS, Mac OS X, VMS and Unix, DOS and MIME, as well as probably other more obscure conventions. +Here is what we do: CR and LF are considered candidates for line break. We issue "one" end-of-line line marker if one of the candidates is seen alone, or followed by a "different" candidate. That is, CR CR and LF LF issue two end of line markers each, but CR LF and LF CR issue only one marker. This idea takes care of Mac OS, Mac OS X, VMS and Unix, DOS and MIME, as well as probably other more obscure conventions. -==The C part of the implementation== +### The C part of the implementation The low-level filter is divided into two simple functions. The inner function actually does the conversion. It takes each input character in turn, deciding what to output and how to modify the context. The context tells if the last character seen was a candidate and, if so, which candidate it was. - {{{ +```c #define candidate(c) (c == CR || c == LF) static int process(int c, int last, const char *marker, luaL_Buffer *buffer) { if (candidate(c)) { @@ -84,10 +81,10 @@ static int process(int c, int last, const char *marker, luaL_Buffer *buffer) { return 0; } } -}}} +``` -The inner function makes use of Lua's auxiliary library's buffer interface for its efficiency and ease of use. The outer function simply interfaces with Lua. It receives the context and the input chunk (as well as an optional end-of-line marker), and returns the transformed output and the new context. - {{{ +The inner function makes use of Lua's auxiliary library's buffer interface for its efficiency and ease of use. The outer function simply interfaces with Lua. It receives the context and the input chunk (as well as an optional end-of-line marker), and returns the transformed output and the new context. +```c static int eol(lua_State *L) { int ctx = luaL_checkint(L, 1); size_t isize = 0; @@ -107,16 +104,16 @@ static int eol(lua_State *L) { lua_pushnumber(L, ctx); return 2; } -}}} +``` -Notice that if the input chunk is {{nil}}, the operation is considered to be finished. In that case, the loop will not execute a single time and the context is reset to the initial state. This allows the filter to be reused indefinitely. It is a good idea to write filters like this, when possible. +Notice that if the input chunk is `nil`, the operation is considered to be finished. In that case, the loop will not execute a single time and the context is reset to the initial state. This allows the filter to be reused indefinitely. It is a good idea to write filters like this, when possible. -Besides the end-of-line normalization filter shown above, many other filters can be implemented with the same ideas. Examples include Base64 and Quoted-Printable transfer content encodings, the breaking of text into lines, SMTP byte stuffing etc. The challenging part is to decide what will be the context. For line breaking, for instance, it could be the number of bytes left in the current line. For Base64 encoding, it could be the bytes that remain in the division of the input into 3-byte atoms. +Besides the end-of-line normalization filter shown above, many other filters can be implemented with the same ideas. Examples include Base64 and Quoted-Printable transfer content encodings, the breaking of text into lines, SMTP byte stuffing etc. The challenging part is to decide what will be the context. For line breaking, for instance, it could be the number of bytes left in the current line. For Base64 encoding, it could be the bytes that remain in the division of the input into 3-byte atoms. -===Chaining=== +## Chaining -Filters become more powerful when the concept of chaining is introduced. Suppose you have a filter for Quoted-Printable encoding and you want to encode some text. According to the standard, the text has to be normalized into its canonic form prior to encoding. A nice interface that simplifies this task is a factory that creates a composite filter that passes data through multiple filters, but that can be used wherever a primitive filter is used. - {{{ +Filters become more powerful when the concept of chaining is introduced. Suppose you have a filter for Quoted-Printable encoding and you want to encode some text. According to the standard, the text has to be normalized into its canonic form prior to encoding. A nice interface that simplifies this task is a factory that creates a composite filter that passes data through multiple filters, but that can be used wherever a primitive filter is used. +```lua local function chain2(f1, f2) return function(chunk) local ret = f2(f1(chunk)) @@ -140,18 +137,18 @@ while 1 do io.write(chain(chunk)) if not chunk then break end end -}}} +``` -The chaining factory is very simple. All it does is return a function that passes data through all filters and returns the result to the user. It uses the simpler auxiliary function that knows how to chain two filters together. In the auxiliary function, special care must be taken if the chunk is final. This is because the final chunk notification has to be pushed through both filters in turn. Thanks to the chain factory, it is easy to perform the Quoted-Printable conversion, as the above example shows. +The chaining factory is very simple. All it does is return a function that passes data through all filters and returns the result to the user. It uses the simpler auxiliary function that knows how to chain two filters together. In the auxiliary function, special care must be taken if the chunk is final. This is because the final chunk notification has to be pushed through both filters in turn. Thanks to the chain factory, it is easy to perform the Quoted-Printable conversion, as the above example shows. -===Sources, sinks, and pumps=== +## Sources, sinks, and pumps As we noted in the introduction, the filters we introduced so far act as the internal nodes in a network of transformations. Information flows from node to node (or rather from one filter to the next) and is transformed on its way out. Chaining filters together is the way we found to connect nodes in the network. But what about the end nodes? In the beginning of the network, we need a node that provides the data, a source. In the end of the network, we need a node that takes in the data, a sink. -==Sources== +### Sources -We start with two simple sources. The first is the {{empty}} source: It simply returns no data, possibly returning an error message. The second is the {{file}} source, which produces the contents of a file in a chunk by chunk fashion, closing the file handle when done. - {{{ +We start with two simple sources. The first is the `empty` source: It simply returns no data, possibly returning an error message. The second is the `file` source, which produces the contents of a file in a chunk by chunk fashion, closing the file handle when done. +```lua function source.empty(err) return function() return nil, err @@ -159,7 +156,7 @@ function source.empty(err) end function source.file(handle, io_err) - if handle then + if handle then return function() local chunk = handle:read(2048) if not chunk then handle:close() end @@ -167,44 +164,44 @@ function source.file(handle, io_err) end else return source.empty(io_err or "unable to open file") end end -}}} +``` -A source returns the next chunk of data each time it is called. When there is no more data, it just returns {{nil}}. If there is an error, the source can inform the caller by returning {{nil}} followed by an error message. Adrian Sietsma noticed that, although not on purpose, the interface for sources is compatible with the idea of iterators in Lua 5.0. That is, a data source can be nicely used in conjunction with {{for}} loops. Using our file source as an iterator, we can rewrite our first example: - {{{ +A source returns the next chunk of data each time it is called. When there is no more data, it just returns `nil`. If there is an error, the source can inform the caller by returning `nil` followed by an error message. Adrian Sietsma noticed that, although not on purpose, the interface for sources is compatible with the idea of iterators in Lua 5.0. That is, a data source can be nicely used in conjunction with `for` loops. Using our file source as an iterator, we can rewrite our first example: +```lua local process = normalize("\r\n") for chunk in source.file(io.stdin) do io.write(process(chunk)) end io.write(process(nil)) -}}} +``` -Notice that the last call to the filter obtains the last chunk of processed data. The loop terminates when the source returns {{nil}} and therefore we need that final call outside of the loop. +Notice that the last call to the filter obtains the last chunk of processed data. The loop terminates when the source returns `nil` and therefore we need that final call outside of the loop. -==Maintaining state between calls== +### Maintaining state between calls -It is often the case that a source needs to change its behavior after some event. One simple example would be a file source that wants to make sure it returns {{nil}} regardless of how many times it is called after the end of file, avoiding attempts to read past the end of the file. Another example would be a source that returns the contents of several files, as if they were concatenated, moving from one file to the next until the end of the last file is reached. +It is often the case that a source needs to change its behavior after some event. One simple example would be a file source that wants to make sure it returns `nil` regardless of how many times it is called after the end of file, avoiding attempts to read past the end of the file. Another example would be a source that returns the contents of several files, as if they were concatenated, moving from one file to the next until the end of the last file is reached. -One way to implement this kind of source is to have the factory declare extra state variables that the source can use via lexical scoping. Our file source could set the file handle itself to {{nil}} when it detects the end-of-file. Then, every time the source is called, it could check if the handle is still valid and act accordingly: - {{{ +One way to implement this kind of source is to have the factory declare extra state variables that the source can use via lexical scoping. Our file source could set the file handle itself to `nil` when it detects the end-of-file. Then, every time the source is called, it could check if the handle is still valid and act accordingly: +```lua function source.file(handle, io_err) - if handle then + if handle then return function() if not handle then return nil end local chunk = handle:read(2048) - if not chunk then - handle:close() + if not chunk then + handle:close() handle = nil end return chunk end else return source.empty(io_err or "unable to open file") end end -}}} +``` -Another way to implement this behavior involves a change in the source interface to makes it more flexible. Let's allow a source to return a second value, besides the next chunk of data. If the returned chunk is {{nil}}, the extra return value tells us what happened. A second {{nil}} means that there is just no more data and the source is empty. Any other value is considered to be an error message. On the other hand, if the chunk was ''not'' {{nil}}, the second return value tells us whether the source wants to be replaced. If it is {{nil}}, we should proceed using the same source. Otherwise it has to be another source, which we have to use from then on, to get the remaining data. +Another way to implement this behavior involves a change in the source interface to makes it more flexible. Let's allow a source to return a second value, besides the next chunk of data. If the returned chunk is `nil`, the extra return value tells us what happened. A second `nil` means that there is just no more data and the source is empty. Any other value is considered to be an error message. On the other hand, if the chunk was "not" `nil`, the second return value tells us whether the source wants to be replaced. If it is `nil`, we should proceed using the same source. Otherwise it has to be another source, which we have to use from then on, to get the remaining data. -This extra freedom is good for someone writing a source function, but it is a pain for those that have to use it. Fortunately, given one of these ''fancy'' sources, we can transform it into a simple source that never needs to be replaced, using the following factory. - {{{ +This extra freedom is good for someone writing a source function, but it is a pain for those that have to use it. Fortunately, given one of these "fancy" sources, we can transform it into a simple source that never needs to be replaced, using the following factory. +```lua function source.simplify(src) return function() local chunk, err_or_new = src() @@ -213,28 +210,28 @@ function source.simplify(src) else return chunk end end end -}}} +``` The simplification factory allows us to write fancy sources and use them as if they were simple. Therefore, our next functions will only produce simple sources, and functions that take sources will assume they are simple. Going back to our file source, the extended interface allows for a more elegant implementation. The new source just asks to be replaced by an empty source as soon as there is no more data. There is no repeated checking of the handle. To make things simpler to the user, the factory itself simplifies the the fancy file source before returning it to the user: - {{{ +```lua function source.file(handle, io_err) - if handle then + if handle then return source.simplify(function() local chunk = handle:read(2048) - if not chunk then + if not chunk then handle:close() - return "", source.empty() + return "", source.empty() end return chunk end) else return source.empty(io_err or "unable to open file") end end -}}} +``` -We can make these ideas even more powerful if we use a new feature of Lua 5.0: coroutines. Coroutines suffer from a great lack of advertisement, and I am going to play my part here. Just like lexical scoping, coroutines taste odd at first, but once you get used with the concept, it can save your day. I have to admit that using coroutines to implement our file source would be overkill, so let's implement a concatenated source factory instead. - {{{ +We can make these ideas even more powerful if we use a new feature of Lua 5.0: coroutines. Coroutines suffer from a great lack of advertisement, and I am going to play my part here. Just like lexical scoping, coroutines taste odd at first, but once you get used with the concept, it can save your day. I have to admit that using coroutines to implement our file source would be overkill, so let's implement a concatenated source factory instead. +```lua function source.cat(...) local arg = {...} local co = coroutine.create(function() @@ -242,22 +239,22 @@ function source.cat(...) while i <= #arg do local chunk, err = arg[i]() if chunk then coroutine.yield(chunk) - elseif err then return nil, err - else i = i + 1 end + elseif err then return nil, err + else i = i + 1 end end end) return function() return shift(coroutine.resume(co)) end end -}}} +``` -The factory creates two functions. The first is an auxiliary that does all the work, in the form of a coroutine. It reads a chunk from one of the sources. If the chunk is {{nil}}, it moves to the next source, otherwise it just yields returning the chunk. When it is resumed, it continues from where it stopped and tries to read the next chunk. The second function is the source itself, and just resumes the execution of the auxiliary coroutine, returning to the user whatever chunks it returns (skipping the first result that tells us if the coroutine terminated). Imagine writing the same function without coroutines and you will notice the simplicity of this implementation. We will use coroutines again when we make the filter interface more powerful. +The factory creates two functions. The first is an auxiliary that does all the work, in the form of a coroutine. It reads a chunk from one of the sources. If the chunk is `nil`, it moves to the next source, otherwise it just yields returning the chunk. When it is resumed, it continues from where it stopped and tries to read the next chunk. The second function is the source itself, and just resumes the execution of the auxiliary coroutine, returning to the user whatever chunks it returns (skipping the first result that tells us if the coroutine terminated). Imagine writing the same function without coroutines and you will notice the simplicity of this implementation. We will use coroutines again when we make the filter interface more powerful. -==Chaining Sources== +### Chaining Sources What does it mean to chain a source with a filter? The most useful interpretation is that the combined source-filter is a new source that produces data and passes it through the filter before returning it. Here is a factory that does it: - {{{ +```lua function source.chain(src, f) return source.simplify(function() local chunk, err = src() @@ -265,14 +262,14 @@ function source.chain(src, f) else return f(chunk) end end) end -}}} +``` Our motivating example in the introduction chains a source with a filter. The idea of chaining a source with a filter is useful when one thinks about functions that might get their input data from a source. By chaining a simple source with one or more filters, the same function can be provided with filtered data even though it is unaware of the filtering that is happening behind its back. -==Sinks== +### Sinks -Just as we defined an interface for an initial source of data, we can also define an interface for a final destination of data. We call any function respecting that interface a ''sink''. Below are two simple factories that return sinks. The table factory creates a sink that stores all obtained data into a table. The data can later be efficiently concatenated into a single string with the {{table.concat}} library function. As another example, we introduce the {{null}} sink: A sink that simply discards the data it receives. - {{{ +Just as we defined an interface for an initial source of data, we can also define an interface for a final destination of data. We call any function respecting that interface a "sink". Below are two simple factories that return sinks. The table factory creates a sink that stores all obtained data into a table. The data can later be efficiently concatenated into a single string with the `table.concat` library function. As another example, we introduce the `null` sink: A sink that simply discards the data it receives. +```lua function sink.table(t) t = t or {} local f = function(chunk, err) @@ -289,12 +286,12 @@ end function sink.null() return null end -}}} +``` -Sinks receive consecutive chunks of data, until the end of data is notified with a {{nil}} chunk. An error is notified by an extra argument giving an error message after the {{nil}} chunk. If a sink detects an error itself and wishes not to be called again, it should return {{nil}}, optionally followed by an error message. A return value that is not {{nil}} means the source will accept more data. Finally, just as sources can choose to be replaced, so can sinks, following the same interface. Once again, it is easy to implement a {{sink.simplify}} factory that transforms a fancy sink into a simple sink. +Sinks receive consecutive chunks of data, until the end of data is notified with a `nil` chunk. An error is notified by an extra argument giving an error message after the `nil` chunk. If a sink detects an error itself and wishes not to be called again, it should return `nil`, optionally followed by an error message. A return value that is not `nil` means the source will accept more data. Finally, just as sources can choose to be replaced, so can sinks, following the same interface. Once again, it is easy to implement a `sink.simplify` factory that transforms a fancy sink into a simple sink. As an example, let's create a source that reads from the standard input, then chain it with a filter that normalizes the end-of-line convention and let's use a sink to place all data into a table, printing the result in the end. - {{{ +```lua local load = source.chain(source.file(io.stdin), normalize("\r\n")) local store, t = sink.table() while 1 do @@ -303,10 +300,10 @@ while 1 do if not chunk then break end end print(table.concat(t)) -}}} +``` -Again, just as we created a factory that produces a chained source-filter from a source and a filter, it is easy to create a factory that produces a new sink given a sink and a filter. The new sink passes all data it receives through the filter before handing it in to the original sink. Here is the implementation: - {{{ +Again, just as we created a factory that produces a chained source-filter from a source and a filter, it is easy to create a factory that produces a new sink given a sink and a filter. The new sink passes all data it receives through the filter before handing it in to the original sink. Here is the implementation: +```lua function sink.chain(f, snk) return function(chunk, err) local r, e = snk(f(chunk)) @@ -315,12 +312,12 @@ function sink.chain(f, snk) return 1 end end -}}} +``` -==Pumps== +### Pumps -There is a while loop that has been around for too long in our examples. It's always there because everything that we designed so far is passive. Sources, sinks, filters: None of them will do anything on their own. The operation of pumping all data a source can provide into a sink is so common that we will provide a couple helper functions to do that for us. - {{{ +There is a while loop that has been around for too long in our examples. It's always there because everything that we designed so far is passive. Sources, sinks, filters: None of them will do anything on their own. The operation of pumping all data a source can provide into a sink is so common that we will provide a couple helper functions to do that for us. +```lua function pump.step(src, snk) local chunk, src_err = src() local ret, snk_err = snk(chunk, src_err) @@ -334,31 +331,31 @@ function pump.all(src, snk, step) if not ret then return not err, err end end end -}}} +``` -The {{pump.step}} function moves one chunk of data from the source to the sink. The {{pump.all}} function takes an optional {{step}} function and uses it to pump all the data from the source to the sink. We can now use everything we have to write a program that reads a binary file from disk and stores it in another file, after encoding it to the Base64 transfer content encoding: - {{{ +The `pump.step` function moves one chunk of data from the source to the sink. The `pump.all` function takes an optional `step` function and uses it to pump all the data from the source to the sink. We can now use everything we have to write a program that reads a binary file from disk and stores it in another file, after encoding it to the Base64 transfer content encoding: +```lua local load = source.chain( - source.file(io.open("input.bin", "rb")), + source.file(io.open("input.bin", "rb")), encode("base64") ) local store = sink.chain( wrap(76), - sink.file(io.open("output.b64", "w")), + sink.file(io.open("output.b64", "w")), ) pump.all(load, store) -}}} +``` -The way we split the filters here is not intuitive, on purpose. Alternatively, we could have chained the Base64 encode filter and the line-wrap filter together, and then chain the resulting filter with either the file source or the file sink. It doesn't really matter. +The way we split the filters here is not intuitive, on purpose. Alternatively, we could have chained the Base64 encode filter and the line-wrap filter together, and then chain the resulting filter with either the file source or the file sink. It doesn't really matter. -===One last important change=== +## One last important change -Turns out we still have a problem. When David Burgess was writing his gzip filter, he noticed that the decompression filter can explode a small input chunk into a huge amount of data. Although we wished we could ignore this problem, we soon agreed we couldn't. The only solution is to allow filters to return partial results, and that is what we chose to do. After invoking the filter to pass input data, the user now has to loop invoking the filter to find out if it has more output data to return. Note that these extra calls can't pass more data to the filter. +Turns out we still have a problem. When David Burgess was writing his gzip filter, he noticed that the decompression filter can explode a small input chunk into a huge amount of data. Although we wished we could ignore this problem, we soon agreed we couldn't. The only solution is to allow filters to return partial results, and that is what we chose to do. After invoking the filter to pass input data, the user now has to loop invoking the filter to find out if it has more output data to return. Note that these extra calls can't pass more data to the filter. -More specifically, after passing a chunk of input data to a filter and collecting the first chunk of output data, the user invokes the filter repeatedly, passing the empty string, to get extra output chunks. When the filter itself returns an empty string, the user knows there is no more output data, and can proceed to pass the next input chunk. In the end, after the user passes a {{nil}} notifying the filter that there is no more input data, the filter might still have produced too much output data to return in a single chunk. The user has to loop again, this time passing {{nil}} each time, until the filter itself returns {{nil}} to notify the user it is finally done. +More specifically, after passing a chunk of input data to a filter and collecting the first chunk of output data, the user invokes the filter repeatedly, passing the empty string, to get extra output chunks. When the filter itself returns an empty string, the user knows there is no more output data, and can proceed to pass the next input chunk. In the end, after the user passes a `nil` notifying the filter that there is no more input data, the filter might still have produced too much output data to return in a single chunk. The user has to loop again, this time passing `nil` each time, until the filter itself returns `nil` to notify the user it is finally done. Most filters won't need this extra freedom. Fortunately, the new filter interface is easy to implement. In fact, the end-of-line translation filter we created in the introduction already conforms to it. On the other hand, the chaining function becomes much more complicated. If it wasn't for coroutines, I wouldn't be happy to implement it. Let me know if you can find a simpler implementation that does not use coroutines! - {{{ +```lua local function chain2(f1, f2) local co = coroutine.create(function(chunk) while true do @@ -380,14 +377,14 @@ local function chain2(f1, f2) return res end end -}}} +``` Chaining sources also becomes more complicated, but a similar solution is possible with coroutines. Chaining sinks is just as simple as it has always been. Interestingly, these modifications do not have a measurable negative impact in the the performance of filters that didn't need the added flexibility. They do severely improve the efficiency of filters like the gzip filter, though, and that is why we are keeping them. -===Final considerations=== +## Final considerations -These ideas were created during the development of {{LuaSocket}}[http://www.tecgraf.puc-rio.br/luasocket] 2.0, and are available as the LTN12 module. As a result, {{LuaSocket}}[http://www.tecgraf.puc-rio.br/luasocket] implementation was greatly simplified and became much more powerful. The MIME module is especially integrated to LTN12 and provides many other filters. We felt these concepts deserved to be made public even to those that don't care about {{LuaSocket}}[http://www.tecgraf.puc-rio.br/luasocket], hence the LTN. +These ideas were created during the development of [LuaSocket](https://github.com/lunarmodules/luasocket) 2.0, and are available as the LTN12 module. As a result, [LuaSocket](https://github.com/lunarmodules/luasocket) implementation was greatly simplified and became much more powerful. The MIME module is especially integrated to LTN12 and provides many other filters. We felt these concepts deserved to be made public even to those that don't care about [LuaSocket](https://github.com/lunarmodules/luasocket), hence the LTN. -One extra application that deserves mentioning makes use of an identity filter. Suppose you want to provide some feedback to the user while a file is being downloaded into a sink. Chaining the sink with an identity filter (a filter that simply returns the received data unaltered), you can update a progress counter on the fly. The original sink doesn't have to be modified. Another interesting idea is that of a T sink: A sink that sends data to two other sinks. In summary, there appears to be enough room for many other interesting ideas. +One extra application that deserves mentioning makes use of an identity filter. Suppose you want to provide some feedback to the user while a file is being downloaded into a sink. Chaining the sink with an identity filter (a filter that simply returns the received data unaltered), you can update a progress counter on the fly. The original sink doesn't have to be modified. Another interesting idea is that of a T sink: A sink that sends data to two other sinks. In summary, there appears to be enough room for many other interesting ideas. -In this technical note we introduced filters, sources, sinks, and pumps. These are useful tools for data processing in general. Sources provide a simple abstraction for data acquisition. Sinks provide an abstraction for final data destinations. Filters define an interface for data transformations. The chaining of filters, sources and sinks provides an elegant way to create arbitrarily complex data transformation from simpler transformations. Pumps just put the machinery to work. +In this technical note we introduced filters, sources, sinks, and pumps. These are useful tools for data processing in general. Sources provide a simple abstraction for data acquisition. Sinks provide an abstraction for final data destinations. Filters define an interface for data transformations. The chaining of filters, sources and sinks provides an elegant way to create arbitrarily complex data transformation from simpler transformations. Pumps just put the machinery to work. diff --git a/ltn013.wiki b/ltn013.wiki index a622424..9c56805 100644 --- a/ltn013.wiki +++ b/ltn013.wiki @@ -1,50 +1,47 @@ -===Using finalized exceptions=== -==or How to get rid of all those if statements== +# Using finalized exceptions +### or How to get rid of all those if statements by DiegoNehab -{{{ -}}} +## Abstract +This little LTN describes a simple exception scheme that greatly simplifies error checking in Lua programs. All the needed functionality ships standard with Lua, but is hidden between the `assert` and `pcall` functions. To make it more evident, we stick to a convenient standard (you probably already use anyways) for Lua function return values, and define two very simple helper functions (either in C or in Lua itself). -===Abstract=== -This little LTN describes a simple exception scheme that greatly simplifies error checking in Lua programs. All the needed functionality ships standard with Lua, but is hidden between the {{assert}} and {{pcall}} functions. To make it more evident, we stick to a convenient standard (you probably already use anyways) for Lua function return values, and define two very simple helper functions (either in C or in Lua itself). +## Introduction -===Introduction=== +Most Lua functions return `nil` in case of error, followed by a message describing the error. If you don't use this convention, you probably have good reasons. Hopefully, after reading on, you will realize your reasons are not good enough. -Most Lua functions return {{nil}} in case of error, followed by a message describing the error. If you don't use this convention, you probably have good reasons. Hopefully, after reading on, you will realize your reasons are not good enough. +If you are like me, you hate error checking. Most nice little code snippets that look beautiful when you first write them lose some of their charm when you add all that error checking code. Yet, error checking is as important as the rest of the code. How sad. -If you are like me, you hate error checking. Most nice little code snippets that look beautiful when you first write them lose some of their charm when you add all that error checking code. Yet, error checking is as important as the rest of the code. How sad. - -Even if you stick to a return convention, any complex task involving several function calls makes error checking both boring and error-prone (do you see the ''error'' below?) - {{{ +Even if you stick to a return convention, any complex task involving several function calls makes error checking both boring and error-prone (do you see the "error" below?) +```lua function task(arg1, arg2, ...) local ret1, err = task1(arg1) - if not ret1 then + if not ret1 then cleanup1() - return nil, error + return nil, error end local ret2, err = task2(arg2) - if not ret then + if not ret then cleanup2() - return nil, error + return nil, error end ... end -}}} +``` -The standard {{assert}} function provides an interesting alternative. To use it, simply nest every function call to be error checked with a call to {{assert}}. The {{assert}} function checks the value of its first argument. If it is {{nil}}, {{assert}} throws the second argument as an error message. Otherwise, {{assert}} lets all arguments through as if had not been there. The idea greatly simplifies error checking: - {{{ +The standard `assert` function provides an interesting alternative. To use it, simply nest every function call to be error checked with a call to `assert`. The `assert` function checks the value of its first argument. If it is `nil`, `assert` throws the second argument as an error message. Otherwise, `assert` lets all arguments through as if had not been there. The idea greatly simplifies error checking: +```lua function task(arg1, arg2, ...) local ret1 = assert(task1(arg1)) local ret2 = assert(task2(arg2)) ... end -}}} +``` -If any task fails, the execution is aborted by {{assert}} and the error message is displayed to the user as the cause of the problem. If no error happens, the task completes as before. There isn't a single {{if}} statement and this is great. However, there are some problems with the idea. +If any task fails, the execution is aborted by `assert` and the error message is displayed to the user as the cause of the problem. If no error happens, the task completes as before. There isn't a single `if` statement and this is great. However, there are some problems with the idea. -First, the topmost {{task}} function doesn't respect the protocol followed by the lower-level tasks: It raises an error instead of returning {{nil}} followed by the error messages. Here is where the standard {{pcall}} comes in handy. - {{{ +First, the topmost `task` function doesn't respect the protocol followed by the lower-level tasks: It raises an error instead of returning `nil` followed by the error messages. Here is where the standard `pcall` comes in handy. +```lua function xtask(arg1, arg2, ...) local ret1 = assert(task1(arg1)) local ret2 = assert(task2(arg2)) @@ -56,22 +53,22 @@ function task(arg1, arg2, ...) if ok then return ret_or_err else return nil, ret_or_err end end -}}} +``` -Our new {{task}} function is well behaved. {{Pcall}} catches any error raised by the calls to {{assert}} and returns it after the status code. That way, errors don't get propagated to the user of the high level {{task}} function. +Our new `task` function is well behaved. `Pcall` catches any error raised by the calls to `assert` and returns it after the status code. That way, errors don't get propagated to the user of the high level `task` function. -These are the main ideas for our exception scheme, but there are still a few glitches to fix: +These are the main ideas for our exception scheme, but there are still a few glitches to fix: - * Directly using {{pcall}} ruined the simplicity of the code; - * What happened to the cleanup function calls? What if we have to, say, close a file? - * {{Assert}} messes with the error message before raising the error (it adds line number information). +* Directly using `pcall` ruined the simplicity of the code; +* What happened to the cleanup function calls? What if we have to, say, close a file? +* `Assert` messes with the error message before raising the error (it adds line number information). -Fortunately, all these problems are very easy to solve and that's what we do in the following sections. +Fortunately, all these problems are very easy to solve and that's what we do in the following sections. -== Introducing the {{protect}} factory == +## Introducing the `protect` factory -We used the {{pcall}} function to shield the user from errors that could be raised by the underlying implementation. Instead of directly using {{pcall}} (and thus duplicating code) every time we prefer a factory that does the same job: - {{{ +We used the `pcall` function to shield the user from errors that could be raised by the underlying implementation. Instead of directly using `pcall` (and thus duplicating code) every time we prefer a factory that does the same job: +```lua local function pack(ok, ...) return ok, {...} end @@ -83,19 +80,19 @@ function protect(f) else return nil, ret[1] end end end -}}} +``` -The {{protect}} factory receives a function that might raise exceptions and returns a function that respects our return value convention. Now we can rewrite the top-level {{task}} function in a much cleaner way: - {{{ +The `protect` factory receives a function that might raise exceptions and returns a function that respects our return value convention. Now we can rewrite the top-level `task` function in a much cleaner way: +```lua task = protect(function(arg1, arg2, ...) local ret1 = assert(task1(arg1)) local ret2 = assert(task2(arg2)) ... end) -}}} +``` -The Lua implementation of the {{protect}} factory suffers with the creation of tables to hold multiple arguments and return values. It is possible (and easy) to implement the same function in C, without any table creation. - {{{ +The Lua implementation of the `protect` factory suffers with the creation of tables to hold multiple arguments and return values. It is possible (and easy) to implement the same function in C, without any table creation. +```c static int safecall(lua_State *L) { lua_pushvalue(L, lua_upvalueindex(1)); lua_insert(L, 1); @@ -110,17 +107,17 @@ static int protect(lua_State *L) { lua_pushcclosure(L, safecall, 1); return 1; } -}}} +``` -===The {{newtry}} factory=== +## The `newtry` factory Let's solve the two remaining issues with a single shot and use a concrete example to illustrate the proposed solution. Suppose you want to write a function to download an HTTP document. You have to connect, send the request and read the reply. Each of these tasks can fail, but if something goes wrong after you connected, you have to close the connection before returning the error message. - {{{ +```lua get = protect(function(host, path) local c -- create a try function with a finalizer to close the socket - local try = newtry(function() - if c then c:close() end + local try = newtry(function() + if c then c:close() end end) -- connect and send request c = try(connect(host, 80)) @@ -137,34 +134,34 @@ get = protect(function(host, path) c:close() return b, h end) -}}} +``` -The {{newtry}} factory returns a function that works just like {{assert}}. The differences are that the {{try}} function doesn't mess with the error message and it calls an optional ''finalizer'' before raising the error. In our example, the finalizer simply closes the socket. +The `newtry` factory returns a function that works just like `assert`. The differences are that the `try` function doesn't mess with the error message and it calls an optional "finalizer" before raising the error. In our example, the finalizer simply closes the socket. -Even with a simple example like this, we see that the finalized exceptions simplified our life. Let's see what we gain in general, not just in this example: +Even with a simple example like this, we see that the finalized exceptions simplified our life. Let's see what we gain in general, not just in this example: - * We don't need to declare dummy variables to hold error messages in case any ever shows up; - * We avoid using a variable to hold something that could either be a return value or an error message; - * We didn't have to use several ''if'' statements to check for errors; - * If an error happens, we know our finalizer is going to be invoked automatically; - * Exceptions get propagated, so we don't repeat these ''if'' statements until the error reaches the user. +* We don't need to declare dummy variables to hold error messages in case any ever shows up; +* We avoid using a variable to hold something that could either be a return value or an error message; +* We didn't have to use several "if" statements to check for errors; +* If an error happens, we know our finalizer is going to be invoked automatically; +* Exceptions get propagated, so we don't repeat these "if" statements until the error reaches the user. -Try writing the same function without the tricks we used above and you will see that the code gets ugly. Longer sequences of operations with error checking would get even uglier. So let's implement the {{newtry}} function in Lua: - {{{ +Try writing the same function without the tricks we used above and you will see that the code gets ugly. Longer sequences of operations with error checking would get even uglier. So let's implement the `newtry` function in Lua: +```lua function newtry(f) - return function(...) - if not arg[1] then - if f then f() end - error(arg[2], 0) - else + return function(...) + if not arg[1] then + if f then f() end + error(arg[2], 0) + else return ... end end end -}}} +``` Again, the implementation suffers from the creation of tables at each function call, so we prefer the C version: - {{{ +```lua static int finalize(lua_State *L) { if (!lua_toboolean(L, 1)) { lua_pushvalue(L, lua_upvalueindex(1)); @@ -182,13 +179,13 @@ static int do_nothing(lua_State *L) { static int newtry(lua_State *L) { lua_settop(L, 1); - if (lua_isnil(L, 1)) + if (lua_isnil(L, 1)) lua_pushcfunction(L, do_nothing); lua_pushcclosure(L, finalize, 1); return 1; } -}}} +``` -===Final considerations=== +## Final considerations -The {{protect}} and {{newtry}} functions saved a ''lot'' of work in the implementation of {{LuaSocket}}[http://www.tecgraf.puc-rio.br/luasocket]. The size of some modules was cut in half by the these ideas. It's true the scheme is not as generic as the exception mechanism of programming languages like C++ or Java, but the power/simplicity ratio is favorable and I hope it serves you as well as it served {{LuaSocket}}. +The `protect` and `newtry` functions saved a "lot" of work in the implementation of [LuaSocket](https://github.com/lunarmodules/luasocket). The size of some modules was cut in half by the these ideas. It's true the scheme is not as generic as the exception mechanism of programming languages like C++ or Java, but the power/simplicity ratio is favorable and I hope it serves you as well as it served [LuaSocket](https://github.com/lunarmodules/luasocket). From 97d5194f302d3fb9fe27874d9b5f73004a208d01 Mon Sep 17 00:00:00 2001 From: Thijs Schreijer Date: Tue, 29 Mar 2022 14:10:30 +0200 Subject: [PATCH 7/7] chore(ltn) rename files to markdown --- ltn012.wiki => ltn012.md | 0 ltn013.wiki => ltn013.md | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename ltn012.wiki => ltn012.md (100%) rename ltn013.wiki => ltn013.md (100%) diff --git a/ltn012.wiki b/ltn012.md similarity index 100% rename from ltn012.wiki rename to ltn012.md diff --git a/ltn013.wiki b/ltn013.md similarity index 100% rename from ltn013.wiki rename to ltn013.md