summaryrefslogtreecommitdiff
path: root/email/utils.scm
diff options
context:
space:
mode:
Diffstat (limited to 'email/utils.scm')
-rw-r--r--email/utils.scm32
1 files changed, 31 insertions, 1 deletions
diff --git a/email/utils.scm b/email/utils.scm
index 35a96d8..2040b21 100644
--- a/email/utils.scm
+++ b/email/utils.scm
@@ -1,5 +1,5 @@
;;; guile-email --- Guile email parser
-;;; Copyright © 2018 Arun Isaac <arunisaac@systemreboot.net>
+;;; Copyright © 2018, 2019 Arun Isaac <arunisaac@systemreboot.net>
;;;
;;; This file is part of guile-email.
;;;
@@ -20,11 +20,17 @@
(define-module (email utils)
#:use-module (ice-9 match)
#:use-module (ice-9 peg codegen)
+ #:use-module (ice-9 binary-ports)
#:use-module (ice-9 textual-ports)
+ #:use-module (rnrs bytevectors)
+ #:use-module ((rnrs io ports)
+ #:select (call-with-bytevector-output-port))
#:use-module (rnrs io simple)
+ #:use-module (srfi srfi-26)
#:export (get-line-with-delimiter
read-objects
read-while
+ read-bytes-till
acons*
alist-delete*))
@@ -52,6 +58,30 @@ string returned by READ-PROC as argument."
(let ((str (call-with-output-string read-while-loop)))
(if (string-null? str) (eof-object) str)))
+(define (read-bytes-till port sequence)
+ "Read bytes from PORT until byte SEQUENCE is seen or end-of-file is
+reached. If SEQUENCE is seen, unget it to PORT and return."
+ (define (read-bytes-and-write-till in out sequence)
+ (let ((octet (get-u8 in)))
+ (cond
+ ((eof-object? octet) octet)
+ ;; If octet read matches first octet of sequence, try matching
+ ;; the full sequence.
+ ((= octet (bytevector-u8-ref sequence 0))
+ (unget-bytevector in sequence 0 1)
+ (let ((bv (get-bytevector-n in (bytevector-length sequence))))
+ (cond
+ ((bytevector=? bv sequence) (unget-bytevector in bv))
+ (else (unget-bytevector in bv 1)
+ (put-u8 out octet)
+ (read-bytes-and-write-till in out sequence)))))
+ ;; Else, output the octet and continue reading.
+ (else (put-u8 out octet)
+ (read-bytes-and-write-till in out sequence)))))
+
+ (call-with-bytevector-output-port
+ (cut read-bytes-and-write-till port <> sequence)))
+
(define (get-line-with-delimiter port)
"Read a line from PORT and return it as a string including the
delimiting linefeed character."