[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Lzip-bug] [lzlib] Help with Scheme bindings (for GNU Guix)

From: Pierre Neidhardt
Subject: [Lzip-bug] [lzlib] Help with Scheme bindings (for GNU Guix)
Date: Tue, 23 Apr 2019 11:10:46 +0200


I'm writing lzlib bindings for GNU Guix in Scheme.
See the work-in-progress patch: http://issues.guix.info/issue/34807

The thing is that Guix takes care of the (un)compressed byte streams at
a higher level, so I essentially need only 2 functions: a
compressor and a decompressor for arbitrary chunks.

Most of the code is rather simple.
The only critical part is the following:

--8<---------------cut here---------------start------------->8---
(define* (lzread! decoder file-port bv
                 #:optional (start 0) (count (bytevector-length bv)))
  "Read up to COUNT bytes from FILE-PORT into BV at offset START.  Return the
number of uncompressed bytes actually read; it is zero if COUNT is zero or if
the end-of-stream has been reached."
  (let* ((written 0)
         (read 0)
         (chunk (* 64 1024))
         (file-bv (get-bytevector-n file-port count)))
    (if (eof-object? file-bv)
          (while (and (< 0 (lz-decompress-write-size decoder))
                      (< written (bytevector-length file-bv)))
            (set! written (lz-decompress-write decoder file-bv written (- 
(bytevector-length file-bv) written))))
          ;; TODO: When should we call `lz-decompress-finish'?
          ;; (lz-decompress-finish decoder)
          ;; TODO: Loop?
          (set! read (lz-decompress-read decoder bv start
                                         (- (bytevector-length bv) start)))

(define* (lzwrite encoder bv lz-port
                  #:optional (start 0) (count (bytevector-length bv)))
  "Write up to COUNT bytes from BV at offset START into LZ-PORT.  Return
the number of uncompressed bytes written, a strictly positive integer."
  (let ((written 0)
        (read 0))
    (while (and (< 0 (lz-compress-write-size encoder))
                (< written count))
      (set! written (lz-compress-write encoder bv (+ start written) (- count 
    (lz-compress-finish encoder)
    (let ((lz-bv (make-bytevector written)))
      (let loop ((rd 0))
        (set! rd (lz-compress-read encoder lz-bv 0 (bytevector-length lz-bv)))
        (put-bytevector lz-port lz-bv 0 rd)
        (set! read (+ read rd))
        (unless (= rd 0)
          (loop rd))))
    ;; TODO: Return written (uncompressed) or read (compressed)?
--8<---------------cut here---------------end--------------->8---

(If you can't read Scheme, I can help, no problem.)

I have a few questions:

1. When am I supposed to call lz_decompress_finish?  In the above
lzread!, you'll see it's commented and it seems to work nonetheless.  If
I uncomment it, it crashes.

2. It's unclear in the manual if the lz-decompress-read reads all the
bytes that were written.  Am I supposed to loop until no more bytes are

3. In both functions, should we *compress_write everything first, then
*compress_read as much as we can?  Or chain write-read calls like in

4. In lzwrite, is "written" the number of uncompressed bytes and "read" the
number of compressed bytes?

Thanks in advance.

Pierre Neidhardt

Attachment: signature.asc
Description: PGP signature

reply via email to

[Prev in Thread] Current Thread [Next in Thread]