ref: 62f894ac7766b7b3ed82d94f092b518fb63308ad
parent: 7b7b65af4f276336d06f43a5c541d5597a405916
author: Lennart Augustsson <lennart@augustsson.net>
date: Tue Oct 1 11:52:33 EDT 2024
More BFILE stuff.
--- a/lib/System/Compress.hs
+++ b/lib/System/Compress.hs
@@ -1,5 +1,7 @@
-module System.Compress(compress) where
+module System.Compress {-(compress)-} where
import Prelude(); import MiniPrelude
+import Data.Function
+import Foreign.Ptr
import Foreign.C.String
import Foreign.C.Types
import Foreign.Marshal.Alloc
@@ -6,6 +8,8 @@
import Foreign.Marshal.Utils
import Foreign.Ptr
import Foreign.Storable
+import System.IO
+import System.IO_Handle
import System.IO.Unsafe
foreign import ccall "lz77c" c_lz77c :: CString -> CSize -> Ptr CString -> IO CSize
@@ -21,3 +25,55 @@
free iptr
free optr
return res
+
+type PBFILE = Ptr BFILE
+foreign import ccall "openb_wr_buf" c_openb_wr_buf :: IO PBFILE
+foreign import ccall "openb_rd_buf" c_openb_rd_buf :: Ptr Char -> Int -> IO PBFILE
+foreign import ccall "add_lz77_compressor" c_add_lz77_compressor :: PBFILE -> IO PBFILE
+foreign import ccall "add_lz77_decompressor" c_add_lz77_decompressor :: PBFILE -> IO PBFILE
+foreign import ccall "putb" c_putb :: Int -> PBFILE -> IO ()
+foreign import ccall "get_buf" c_get_buf :: PBFILE -> Ptr (Ptr Char) -> Ptr Int -> IO ()
+
+withPutTransducer :: (PBFILE -> IO PBFILE) -> [Char] -> [Char]
+withPutTransducer trans file = unsafePerformIO $ do
+ bf <- c_openb_wr_buf
+ cbf <- trans bf
+ mapM_ (flip c_putb cbf . ord) file
+ with nullPtr $ \ bufp ->
+ with 0 $ \ lenp -> do
+ c_get_buf bf bufp lenp
+ buf <- peek bufp
+ len <- peek lenp
+ res <- peekCAStringLen (buf, len)
+ free buf
+ return res
+
+withGetTransducer :: (PBFILE -> IO PBFILE) -> [Char] -> [Char]
+withGetTransducer trans file = unsafePerformIO $ do
+ (ptr, len) <- newCAStringLen file
+ bf <- c_openb_rd_buf ptr len >>= trans
+ h <- mkHandle "withGetTransducer" bf
+ hGetContents h
+
+compress' :: [Char] -> [Char]
+compress' = withPutTransducer c_add_lz77_compressor
+
+decompress :: [Char] -> [Char]
+decompress = withGetTransducer c_add_lz77_decompressor
+
+main :: IO ()
+main = do
+ haa <- openBinaryFile "aa" ReadMode
+ putStrLn "AA"
+ aa <- hGetContents haa
+ putStrLn "BB"
+ let bb = compress' aa
+ putStrLn "CC"
+ hbb <- openBinaryFile "bb" WriteMode
+ putStrLn "DD"
+ hPutStr hbb bb
+ putStrLn "EE"
+ hClose hbb
+ putStrLn "FF"
+ hClose haa
+ putStrLn "GG"
--- a/src/MicroHs/FFI.hs
+++ b/src/MicroHs/FFI.hs
@@ -185,5 +185,6 @@
"peek_ullong", "poke_ullong", "peek_llong", "poke_llong",
"peek_flt", "poke_flt",
"sizeof_int", "sizeof_long", "sizeof_llong",
- "opendir", "closedir", "readdir", "c_d_name", "chdir", "mkdir", "getcwd"
+ "opendir", "closedir", "readdir", "c_d_name", "chdir", "mkdir", "getcwd",
+ "get_buf", "openb_rd_buf", "openb_wr_buf"
]
--- a/src/runtime/bfile.c
+++ b/src/runtime/bfile.c
@@ -23,7 +23,11 @@
*/
/* Sanity checking */
-#define CHECKBFILE(p, f) do { if (p->getb != f) ERR("CHECKBFILE"); } while(0)
+void foo(void)
+{
+ printf("foo\n");
+}
+#define CHECKBFILE(p, f) do { if (p->getb != f) { foo(); ERR("CHECKBFILE"); } } while(0)
/* BFILE will have different implementations, they all have these methods */
typedef struct BFILE {
@@ -108,7 +112,7 @@
}
}
-/***************** BFILE from static buffer *******************/
+/***************** BFILE from/to memory buffer *******************/
struct BFILE_buffer {
BFILE mets;
size_t b_size;
@@ -127,6 +131,20 @@
}
void
+putb_buf(int c, BFILE *bp)
+{
+ struct BFILE_buffer *p = (struct BFILE_buffer *)bp;
+ CHECKBFILE(bp, getb_buf);
+ if (p->b_pos >= p->b_size) {
+ p->b_size *= 2;
+ p->b_buffer = realloc(p->b_buffer, p->b_size);
+ if (!p->b_buffer)
+ ERR("putb_buf");
+ }
+ p->b_buffer[p->b_pos++] = c;
+}
+
+void
ungetb_buf(int c, BFILE *bp)
{
struct BFILE_buffer *p = (struct BFILE_buffer *)bp;
@@ -137,17 +155,29 @@
}
void
-closeb_buf(BFILE *bp)
+closeb_rd_buf(BFILE *bp)
{
CHECKBFILE(bp, getb_buf);
FREE(bp);
}
-/* There is no open(). Only used with statically allocated buffers. */
+void
+closeb_wr_buf(BFILE *bp)
+{
+ CHECKBFILE(bp, getb_buf);
+ FREE(bp);
+}
+
+void
+flushb_buf(BFILE *bp)
+{
+ CHECKBFILE(bp, getb_buf);
+}
+
struct BFILE*
-openb_buf(uint8_t *buf, size_t len)
+openb_rd_buf(uint8_t *buf, size_t len)
{
- struct BFILE_buffer *p = MALLOC(sizeof(struct BFILE_buffer));;
+ struct BFILE_buffer *p = MALLOC(sizeof(struct BFILE_buffer));
if (!p)
memerr();
p->mets.getb = getb_buf;
@@ -154,11 +184,46 @@
p->mets.ungetb = ungetb_buf;
p->mets.putb = 0;
p->mets.flushb = 0;
- p->mets.closeb = closeb_buf;
+ p->mets.closeb = closeb_rd_buf;
p->b_size = len;
p->b_pos = 0;
p->b_buffer = buf;
return (struct BFILE*)p;
+}
+
+struct BFILE*
+openb_wr_buf(void)
+{
+ struct BFILE_buffer *p = MALLOC(sizeof(struct BFILE_buffer));
+ if (!p)
+ memerr();
+ p->mets.getb = getb_buf; /* Just to make CHECKFILE happy */
+ p->mets.ungetb = 0;
+ p->mets.putb = putb_buf;
+ p->mets.flushb = flushb_buf;
+ p->mets.closeb = closeb_wr_buf;
+ p->b_size = 1000;
+ p->b_pos = 0;
+ p->b_buffer = malloc(p->b_size);
+ if (!p->b_buffer)
+ ERR("openb_wr_buf");
+ return (struct BFILE*)p;
+}
+
+/*
+ * Get the buffer used by writing.
+ * This should be the last operation before closing,
+ * since the buffer can move when writing.
+ * The caller of openb_wr_buf() and get_buf() owns
+ * the memory and must free it.
+ */
+void
+get_buf(struct BFILE *bp, uint8_t **bufp, size_t *lenp)
+{
+ struct BFILE_buffer *p = (struct BFILE_buffer *)bp;
+ CHECKBFILE(bp, getb_buf);
+ *bufp = p->b_buffer;
+ *lenp = p->b_pos;
}
#if WANT_STDIO
--- a/src/runtime/eval.c
+++ b/src/runtime/eval.c
@@ -2434,7 +2434,7 @@
NODEPTR
mkStringU(struct bytestring bs)
{
- BFILE *ubuf = add_utf8(openb_buf(bs.string, bs.size));
+ BFILE *ubuf = add_utf8(openb_rd_buf(bs.string, bs.size));
NODEPTR n, *np, nc;
//printf("mkStringU %d %s\n", (int)bs.size, (char*)bs.string);
@@ -4082,7 +4082,7 @@
if (combexpr) {
int c;
- BFILE *bf = openb_buf(combexpr, combexprlen);
+ BFILE *bf = openb_rd_buf(combexpr, combexprlen);
c = getb(bf);
/* Compressed combinators start with a 'Z' or 'z', otherwise 'v' (for version) */
if (c == 'z') {
@@ -4308,6 +4308,9 @@
void mhs_getb(int s) { mhs_from_Int(s, 1, getb(mhs_to_Ptr(s, 0))); }
void mhs_putb(int s) { putb(mhs_to_Int(s, 0), mhs_to_Ptr(s, 1)); mhs_from_Unit(s, 2); }
void mhs_ungetb(int s) { ungetb(mhs_to_Int(s, 0), mhs_to_Ptr(s, 1)); mhs_from_Unit(s, 2); }
+void mhs_openwrbuf(int s) { mhs_from_Ptr(s, 0, openb_wr_buf()); }
+void mhs_openrdbuf(int s) { mhs_from_Ptr(s, 2, openb_rd_buf(mhs_to_Ptr(s, 0), mhs_to_Int(s, 1))); }
+void mhs_getbuf(int s) { get_buf(mhs_to_Ptr(s, 0), mhs_to_Ptr(s, 1), mhs_to_Ptr(s, 2)); mhs_from_Unit(s, 3); }
void mhs_system(int s) { mhs_from_Int(s, 1, system(mhs_to_Ptr(s, 0))); }
void mhs_tmpname(int s) { mhs_from_Ptr(s, 2, TMPNAME(mhs_to_Ptr(s, 0), mhs_to_Ptr(s, 1))); }
void mhs_unlink(int s) { mhs_from_Int(s, 1, unlink(mhs_to_Ptr(s, 0))); }
@@ -4411,6 +4414,7 @@
#if WANT_STDIO
{ "add_FILE", mhs_add_FILE},
{ "add_utf8", mhs_add_utf8},
+//{ "add_rle", mhs_add_rle},
{ "closeb", mhs_closeb},
{ "&closeb", mhs_addr_closeb},
{ "flushb", mhs_flushb},
@@ -4418,6 +4422,9 @@
{ "getb", mhs_getb},
{ "putb", mhs_putb},
{ "ungetb", mhs_ungetb},
+{ "openb_wr_buf", mhs_openwrbuf},
+{ "openn_rd_buf", mhs_openrdbuf},
+{ "get_buf", mhs_getbuf},
{ "system", mhs_system},
{ "tmpname", mhs_tmpname},
{ "unlink", mhs_unlink},