|
90 | 90 | ) ;define-constant |
91 | 91 |
|
92 | 92 | (define (bytevector-base64-decode bv) |
93 | | - (define (decode c1 c2 c3 c4) |
94 | | - (let* ((b1 (BASE64_TO_BYTE_V c1)) |
95 | | - (b2 (BASE64_TO_BYTE_V c2)) |
96 | | - (b3 (BASE64_TO_BYTE_V c3)) |
97 | | - (b4 (BASE64_TO_BYTE_V c4)) |
98 | | - ) ; |
99 | | - (if (or (negative? b1) |
100 | | - (negative? b2) |
101 | | - (and (negative? b3) (not (equal? c3 BASE64_PAD_BYTE))) |
102 | | - (and (negative? b4) (not (equal? c4 BASE64_PAD_BYTE))) |
103 | | - ) ;or |
104 | | - (value-error "Invalid base64 input") |
105 | | - (values (bitwise-ior (ash b1 2) (ash b2 -4)) |
106 | | - (bitwise-and (bitwise-ior (ash b2 4) (ash b3 -2)) 255) |
107 | | - (bitwise-and (bitwise-ior (ash b3 6) b4) 255) |
108 | | - (if (negative? b3) 1 (if (negative? b4) 2 3)) |
109 | | - ) ;values |
110 | | - ) ;if |
111 | | - ) ;let* |
112 | | - ) ;define |
113 | | - (let* ((input-N (bytevector-length bv)) |
114 | | - (output-N (* input-N 3/4)) |
115 | | - (output (make-bytevector output-N)) |
116 | | - ) ; |
| 93 | + (unless (bytevector? bv) |
| 94 | + (type-error "input must be bytevector") |
| 95 | + ) ;unless |
| 96 | + (let ((input-N (bytevector-length bv))) |
117 | 97 | (unless (zero? (modulo input-N 4)) |
118 | 98 | (value-error "length of the input bytevector must be 4X") |
119 | 99 | ) ;unless |
120 | | - (let loop |
121 | | - ((i 0) (j 0)) |
122 | | - (if (< i input-N) |
123 | | - (receive (r1 r2 r3 cnt) |
124 | | - (decode (bv i) (bv (+ i 1)) (bv (+ i 2)) (bv (+ i 3))) |
125 | | - (bytevector-u8-set! output j r1) |
126 | | - (when (>= cnt 2) |
127 | | - (bytevector-u8-set! output (+ j 1) r2) |
128 | | - ) ;when |
129 | | - (when (>= cnt 3) |
130 | | - (bytevector-u8-set! output (+ j 2) r3) |
131 | | - ) ;when |
132 | | - (loop (+ i 4) (+ j cnt)) |
133 | | - ) ;receive |
134 | | - (let ((final (make-bytevector j))) |
135 | | - (vector-copy! final 0 output 0 j) |
136 | | - final |
| 100 | + (define (decode c1 c2 c3 c4) |
| 101 | + (define pad? (lambda (c) (equal? c BASE64_PAD_BYTE))) |
| 102 | + (define c3-pad? (pad? c3)) |
| 103 | + (define c4-pad? (pad? c4)) |
| 104 | + (define b1 (BASE64_TO_BYTE_V c1)) |
| 105 | + (define b2 (BASE64_TO_BYTE_V c2)) |
| 106 | + (define b3 (BASE64_TO_BYTE_V c3)) |
| 107 | + (define b4 (BASE64_TO_BYTE_V c4)) |
| 108 | + (unless (and (not (pad? c1)) |
| 109 | + (not (pad? c2)) |
| 110 | + (not (negative? b1)) |
| 111 | + (not (negative? b2)) |
| 112 | + (or (and (not c3-pad?) (not c4-pad?) (not (negative? b3)) (not (negative? b4))) |
| 113 | + (and (not c3-pad?) c4-pad? (not (negative? b3))) |
| 114 | + (and c3-pad? c4-pad?) |
| 115 | + ) ;or |
| 116 | + ) ;and |
| 117 | + (value-error "Invalid base64 input") |
| 118 | + ) ;unless |
| 119 | + (values (bitwise-ior (ash b1 2) (ash b2 -4)) |
| 120 | + (if c3-pad? 0 (bitwise-and (bitwise-ior (ash b2 4) (ash b3 -2)) 255)) |
| 121 | + (if c4-pad? 0 (bitwise-and (bitwise-ior (ash b3 6) b4) 255)) |
| 122 | + (if c3-pad? 1 (if c4-pad? 2 3)) |
| 123 | + ) ;values |
| 124 | + ) ;define |
| 125 | + (let ((output-N (quotient (* input-N 3) 4))) |
| 126 | + (let ((output (make-bytevector output-N))) |
| 127 | + (let loop |
| 128 | + ((i 0) (j 0)) |
| 129 | + (if (< i input-N) |
| 130 | + (receive (r1 r2 r3 cnt) |
| 131 | + (decode (bv i) (bv (+ i 1)) (bv (+ i 2)) (bv (+ i 3))) |
| 132 | + (bytevector-u8-set! output j r1) |
| 133 | + (when (>= cnt 2) |
| 134 | + (bytevector-u8-set! output (+ j 1) r2) |
| 135 | + ) ;when |
| 136 | + (when (>= cnt 3) |
| 137 | + (bytevector-u8-set! output (+ j 2) r3) |
| 138 | + ) ;when |
| 139 | + (loop (+ i 4) (+ j cnt)) |
| 140 | + ) ;receive |
| 141 | + (let ((final (make-bytevector j))) |
| 142 | + (vector-copy! final 0 output 0 j) |
| 143 | + final |
| 144 | + ) ;let |
| 145 | + ) ;if |
137 | 146 | ) ;let |
138 | | - ) ;if |
| 147 | + ) ;let |
139 | 148 | ) ;let |
140 | | - ) ;let* |
| 149 | + ) ;let |
141 | 150 | ) ;define |
142 | 151 |
|
143 | 152 | (define string-base64-decode |
|
0 commit comments