summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--chickadee/base64.scm33
1 files changed, 21 insertions, 12 deletions
diff --git a/chickadee/base64.scm b/chickadee/base64.scm
index 6575785..b15fec6 100644
--- a/chickadee/base64.scm
+++ b/chickadee/base64.scm
@@ -57,15 +57,21 @@
alphabet)
bv))
-(define* (base64-decode str #:optional (alphabet base64-alphabet))
+(define* (base64-decode str #:key (alphabet base64-alphabet) (padding? #t))
"Decode the base64 encoded string @var{str} using @var{alphabet} and
-return a bytevector containing the decoded data."
+return a bytevector containing the decoded data. If @var{padding?} is
+@code{#t} then trailing padding characters are expected in the input."
(define decoder (alphabet->decoder alphabet))
+ (define (fail) (error "invalid base64" str))
(define (decode char)
+ (unless (char? char) (fail))
(let ((x (bytevector-s8-ref decoder (char->integer char))))
- (when (eq? x -1)
- (error "invalid base64 character" char))
+ (when (eq? x -1) (fail))
x))
+ (define pad?
+ (if padding?
+ (lambda (x) (eq? x #\=))
+ eof-object?))
(call-with-input-string str
(lambda (in)
(call-with-output-bytevector
@@ -77,8 +83,8 @@ return a bytevector containing the decoded data."
(c (read-char in))
(d (read-char in)))
(cond
- ((eq? d #\=)
- (if (eq? c #\=)
+ ((pad? d)
+ (if (pad? c)
;; 2 bytes of padding.
(let ((x (logior (ash (decode a) 6) (decode b))))
(put-u8 out (ash (logand x #xff0) -4)))
@@ -89,8 +95,7 @@ return a bytevector containing the decoded data."
(put-u8 out (ash (logand x #x3fc00) -10))
(put-u8 out (ash (logand x #x3fc) -2))))
;; Input should be fully consumed at this point.
- (unless (eof-object? (peek-char in))
- (error "invalid base64 string" str)))
+ (unless (eof-object? (peek-char in)) (fail)))
(else
(let ((x (logior (ash (decode a) 18)
(ash (decode b) 12)
@@ -108,9 +113,11 @@ return a bytevector containing the decoded data."
alphabet)
bv))
-(define* (base64-encode bv #:optional (alphabet base64-alphabet))
+(define* (base64-encode bv #:key (alphabet base64-alphabet) (padding? #t))
"Encode the bytevector @var{bv} as base64 using
-@var{alphabet} and return a string containing the encoded data."
+@var{alphabet} and return a string containing the encoded data. If
+@var{padding?} is @code{#t} then trailing padding characters are
+included in the output."
(define encoder (alphabet->encoder alphabet))
(define len (bytevector-length bv))
(define groups (quotient len 3))
@@ -133,9 +140,11 @@ return a bytevector containing the decoded data."
(put-char port (encode (ash (logand x #xfc00) -10)))
(put-char port (encode (ash (logand x #x03f0) -4)))
(put-char port (encode (ash (logand x #x000f) 2)))
- (put-char port #\=)))
+ (when padding?
+ (put-char port #\=))))
((eq? padding 2)
(let ((x (bytevector-u8-ref bv offset)))
(put-char port (encode (ash (logand x #xfc) -2)))
(put-char port (encode (ash (logand x #x03) 4)))
- (put-string port "==")))))))))
+ (when padding?
+ (put-string port "=="))))))))))