>From 9043cf8adea070fa2c714e7295389d908101d912 Mon Sep 17 00:00:00 2001 From: apache2 Date: Sun, 10 Apr 2022 12:15:40 +0200 Subject: [PATCH] with_cur_ios function --- doc/poke.texi | 35 +++++++++++++++++++++++++++++++++++ libpoke/pkl-rt.pk | 21 +++++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/doc/poke.texi b/doc/poke.texi index 2c8201e0..8a315307 100644 --- a/doc/poke.texi +++ b/doc/poke.texi @@ -12644,6 +12644,7 @@ memory of some process. * get_ios:: Getting the current IO space. * set_ios:: Setting the current IO space. * openset:: Opening and setting combined. +* with_cur_ios:: Exception-safe IO wrapper. * iosize:: Getting the size of an IO space. * iohandler:: Getting the handler string of an IO space. * ioflags:: Getting the flags of an IO space. @@ -12859,6 +12860,40 @@ fun openset = (string @var{handler}, uint<64> @var{flags} = 0) int<32> Where the meaning of @var{handler}, @var{flags} and the returned value are exactly like in @code{open}. +@node with_cur_ios +@subsubsection @code{with_cur_ios} +@cindex @code{with_cur_ios} + +@example +fun with_cur_ios = (string @var{handle}, With_Ios_Fn do = lambda void:{}, uint<64> flags = 0) void +@end example + +The @code{with_cur_ios} utility function opens a IO space, like @code{openset}, +but takes care of calling @code{close} and restoring the original current IO space +after the lambda returns or raises an exception. + +It can be used to deal with files without risk of leaking file descriptors. + +@example +with_cur_ios("*buf*", lambda void: + @{ + var arr = uint<32>[1] @ 0#B; + arr[0] = 0x1234; + printf("%v", byte[4] @ 0#b); + @}); +[0x00UB,0x00UB,0x12UB,0x34UB] + +with_cur_ios + :handle "*buf*" + :flags IOS_F_CREATE + :do lambda void: + @{ + var arr = uint<32>[1] @ 0#B; + arr[0] = 0x1234; + printf("%v", byte[4] @ 0#b); + @} +@end example + @node iosize @subsubsection @code{iosize} @cindex @code{iosize} diff --git a/libpoke/pkl-rt.pk b/libpoke/pkl-rt.pk index c6b3209c..03d39970 100644 --- a/libpoke/pkl-rt.pk +++ b/libpoke/pkl-rt.pk @@ -563,6 +563,27 @@ immutable fun _pkl_run_ios_set_hook = (int<32> ios) void: f (ios); } +immutable type With_Ios_Fn = () void; + +immutable fun with_cur_ios = (string handle, With_Ios_Fn do = lambda void:{}, uint<32> flags = 0) void: +{ + var old_ios = get_ios ?! E_no_ios ? get_ios : -1; + var new_ios = open(handle, flags); + set_ios(new_ios); + try + { + do(); + close(new_ios); + if (-1 != old_ios) set_ios(old_ios); + } + catch (Exception exc) + { + close(new_ios); + if (-1 != old_ios) set_ios(old_ios); + raise exc; + } +} + /**** Set the default load path ****/ immutable var load_path = ""; -- 2.30.2