unofficial mirror of guile-devel@gnu.org 
 help / color / mirror / Atom feed
From: Christopher Baines <mail@cbaines.net>
To: guile-devel@gnu.org
Subject: [PATCH] Make get-bytevector-all suspendable.
Date: Thu, 20 Jul 2023 15:01:03 +0100	[thread overview]
Message-ID: <20230720140103.23221-1-mail@cbaines.net> (raw)

I'm looking at this since it's used in (web response)
read-response-body.

* module/ice-9/suspendable-ports.scm (get-bytevector-all): New
procedure.
(port-bindings): Add it.
---
 module/ice-9/suspendable-ports.scm | 36 ++++++++++++++++++++++++++++++
 1 file changed, 36 insertions(+)

diff --git a/module/ice-9/suspendable-ports.scm b/module/ice-9/suspendable-ports.scm
index 9fac1df62..e5b3de982 100644
--- a/module/ice-9/suspendable-ports.scm
+++ b/module/ice-9/suspendable-ports.scm
@@ -50,6 +50,7 @@
 
 (define-module (ice-9 suspendable-ports)
   #:use-module (rnrs bytevectors)
+  #:use-module (rnrs bytevectors gnu)
   #:use-module (ice-9 ports internal)
   #:use-module (ice-9 match)
   #:export (current-read-waiter
@@ -342,6 +343,40 @@
                 (set-port-buffer-cur! buf (+ cur transfer-size))
                 transfer-size))))))
 
+(define (get-bytevector-all port)
+  (define %initial-length 4096)
+
+  (let read-loop ((total 0)
+                  (result-length %initial-length)
+                  (result (make-bytevector %initial-length)))
+    (call-with-values (lambda () (fill-input port 1 'binary))
+      (lambda (buf cur buffered)
+        (if (zero? buffered)
+            (begin
+              (set-port-buffer-has-eof?! buf #f)
+              (if (= total 0)
+                  the-eof-object
+                  (bytevector-slice result 0 total)))
+            (let* ((new-total (+ total buffered))
+                   (new-result-length
+                    (let loop ((new-result-length result-length))
+                      (if (< new-total new-result-length)
+                          new-result-length
+                          (loop (* 2 new-result-length)))))
+                   (new-result
+                    (if (= new-result-length result-length)
+                        result
+                        (let ((new-result (make-bytevector new-result-length)))
+                          (bytevector-copy! result 0 new-result 0 total)
+                          new-result))))
+              (bytevector-copy! (port-buffer-bytevector buf) cur
+                                new-result total
+                                buffered)
+              (set-port-buffer-cur! buf (+ cur buffered))
+              (read-loop new-total
+                         new-result-length
+                         new-result)))))))
+
 (define (put-u8 port byte)
   (let* ((buf (port-write-buffer port))
          (bv (port-buffer-bytevector buf))
@@ -754,6 +789,7 @@
     ((ice-9 binary-ports)
      get-u8 lookahead-u8 get-bytevector-n get-bytevector-n!
      get-bytevector-some get-bytevector-some!
+     get-bytevector-all
      put-u8 put-bytevector)
     ((ice-9 textual-ports)
      put-char put-string)
-- 
2.41.0




                 reply	other threads:[~2023-07-20 14:01 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/guile/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230720140103.23221-1-mail@cbaines.net \
    --to=mail@cbaines.net \
    --cc=guile-devel@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).