-
Notifications
You must be signed in to change notification settings - Fork 3
/
base64.lisp
54 lines (50 loc) · 1.57 KB
/
base64.lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
(defconstant +ALPHABET+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ\
abcdefghijklmnopqrstuvwxyz\
0123456789+/")
(defun base64-encode (x)
(let ((res "")
(acc 0)
(bits 0))
(dolist (c x)
(when (string? c)
(setf c (logand (char-code c) 255)))
(setf acc (+ (ash acc 8) c))
(incf bits 8)
(do () ((< bits 6))
(incf res (aref +ALPHABET+ (ash acc (- 6 bits))))
(decf bits 6)
(setf acc (logand acc (1- (ash 1 bits))))))
(do () ((< bits 1))
(incf res (aref +ALPHABET+ (ash acc (- 6 bits))))
(decf bits 6)
(setf acc (logand acc (1- (ash 1 bits)))))
(when (% (length res) 4)
(incf res (slice "===" 0 (- 4 (% (length res) 4)))))
res))
(defun base64-decode (x)
(let ((res "")
(acc 0)
(bits 0))
(dolist (b x)
(cond
((<= "A" b "Z")
(setf acc (+ (ash acc 6) (- (char-code b) #.(char-code "A"))))
(incf bits 6))
((<= "a" b "z")
(setf acc (+ (ash acc 6) (- (char-code b) (- #.(char-code "a") 26))))
(incf bits 6))
((<= "0" b "9")
(setf acc (+ (ash acc 6) (- (char-code b) (- #.(char-code "0") 52))))
(incf bits 6))
((= b "+")
(setf acc (+ (ash acc 6) 62))
(incf bits 6))
((= b "/")
(setf acc (+ (ash acc 6) 63))
(incf bits 6)))
(do () ((< bits 8))
(incf res (char (ash acc (- 8 bits))))
(decf bits 8)
(setf acc (logand acc (1- (ash 1 bits))))))
res))
(export base64-encode base64-decode)