-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathBase64.bas
163 lines (136 loc) · 5.87 KB
/
Base64.bas
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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
'-----------------------------------------------------------------------------------------------------------------------
' Base64 resource loading library
' Copyright (c) 2024 Samuel Gomes
'-----------------------------------------------------------------------------------------------------------------------
$INCLUDEONCE
''' @brief Loads a binary file encoded with Bin2Data (CONST).
''' @param src The base64 STRING containing the encoded data.
''' @param ogSize The original size of the data.
''' @param isComp Whether the data is compressed.
''' @return The normal STRING or binary data.
FUNCTION Base64_LoadResourceString$ (src AS STRING, ogSize AS _UNSIGNED LONG, isComp AS _BYTE)
' Decode the data
$IF VERSION < 4.1.0 THEN
DIM buffer AS STRING: buffer = Base64_Decode$(src)
$ELSE
DIM buffer AS STRING: buffer = _BASE64DECODE$(src)
$END IF
' Expand the data if needed
IF isComp THEN buffer = _INFLATE$(buffer, ogSize)
Base64_LoadResourceString = buffer
END FUNCTION
''' @brief Loads a binary file encoded with Bin2Data (DATA).
''' Usage:
''' 1. Encode the binary file with Bin2Data.
''' 2. Include the file or its contents.
''' 3. Load the file like so:
''' Restore label_generated_by_bin2data
''' Dim buffer As String
''' buffer = Base64_LoadResourceData
''' @return The normal STRING or binary data.
FUNCTION Base64_LoadResourceData$
DIM ogSize AS _UNSIGNED LONG, datSize AS _UNSIGNED LONG, isComp AS _BYTE
READ ogSize, datSize, isComp ' read the header
DIM buffer AS STRING: buffer = SPACE$(datSize) ' preallocate complete buffer
' Read the whole resource data
DIM i AS _UNSIGNED LONG: DO WHILE i < datSize
DIM chunk AS STRING: READ chunk
MID$(buffer, i + 1) = chunk
i = i + LEN(chunk)
LOOP
' Decode the data
$IF VERSION < 4.1.0 THEN
buffer = Base64_Decode$(buffer)
$ELSE
buffer = _BASE64DECODE$(buffer)
$END IF
' Expand the data if needed
IF isComp THEN buffer = _INFLATE$(buffer, ogSize)
Base64_LoadResourceData = buffer
END FUNCTION
' These are here just until we get to the QB64-PE 4.1.0 release
$IF VERSION < 4.1.0 THEN
' Converts a normal string or binary data to a base64 string
FUNCTION Base64_Encode$ (s AS STRING)
CONST BASE64_CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
DIM srcSize AS _UNSIGNED LONG: srcSize = LEN(s)
DIM srcSize3rem AS _UNSIGNED LONG: srcSize3rem = srcSize MOD 3
DIM srcSize3mul AS _UNSIGNED LONG: srcSize3mul = srcSize - srcSize3rem
DIM buffer AS STRING: buffer = SPACE$(((srcSize + 2) \ 3) * 4) ' preallocate complete buffer
DIM j AS _UNSIGNED LONG: j = 1
DIM i AS _UNSIGNED LONG: FOR i = 1 TO srcSize3mul STEP 3
DIM char1 AS _UNSIGNED _BYTE: char1 = ASC(s, i)
DIM char2 AS _UNSIGNED _BYTE: char2 = ASC(s, i + 1)
DIM char3 AS _UNSIGNED _BYTE: char3 = ASC(s, i + 2)
ASC(buffer, j) = ASC(BASE64_CHARACTERS, 1 + (_SHR(char1, 2)))
j = j + 1
ASC(buffer, j) = ASC(BASE64_CHARACTERS, 1 + (_SHL((char1 AND 3), 4) OR _SHR(char2, 4)))
j = j + 1
ASC(buffer, j) = ASC(BASE64_CHARACTERS, 1 + (_SHL((char2 AND 15), 2) OR _SHR(char3, 6)))
j = j + 1
ASC(buffer, j) = ASC(BASE64_CHARACTERS, 1 + (char3 AND 63))
j = j + 1
NEXT i
' Add padding
IF srcSize3rem > 0 THEN
char1 = ASC(s, i)
ASC(buffer, j) = ASC(BASE64_CHARACTERS, 1 + (_SHR(char1, 2)))
j = j + 1
IF srcSize3rem = 1 THEN
ASC(buffer, j) = ASC(BASE64_CHARACTERS, 1 + (_SHL(char1 AND 3, 4)))
j = j + 1
ASC(buffer, j) = 61 ' "="
j = j + 1
ASC(buffer, j) = 61 ' "="
ELSE ' srcSize3rem = 2
char2 = ASC(s, i + 1)
ASC(buffer, j) = ASC(BASE64_CHARACTERS, 1 + (_SHL((char1 AND 3), 4) OR _SHR(char2, 4)))
j = j + 1
ASC(buffer, j) = ASC(BASE64_CHARACTERS, 1 + (_SHL(char2 AND 15, 2)))
j = j + 1
ASC(buffer, j) = 61 ' "="
END IF
END IF
Base64_Encode = buffer
END FUNCTION
' Converts a base64 string to a normal string or binary data
FUNCTION Base64_Decode$ (s AS STRING)
DIM srcSize AS _UNSIGNED LONG: srcSize = LEN(s)
DIM buffer AS STRING: buffer = SPACE$((srcSize \ 4) * 3) ' preallocate complete buffer
DIM j AS _UNSIGNED LONG: j = 1
DIM AS _UNSIGNED _BYTE index, char1, char2, char3, char4
DIM i AS _UNSIGNED LONG: FOR i = 1 TO srcSize STEP 4
index = ASC(s, i): GOSUB find_index: char1 = index
index = ASC(s, i + 1): GOSUB find_index: char2 = index
index = ASC(s, i + 2): GOSUB find_index: char3 = index
index = ASC(s, i + 3): GOSUB find_index: char4 = index
ASC(buffer, j) = _SHL(char1, 2) OR _SHR(char2, 4)
j = j + 1
ASC(buffer, j) = _SHL(char2 AND 15, 4) OR _SHR(char3, 2)
j = j + 1
ASC(buffer, j) = _SHL(char3 AND 3, 6) OR char4
j = j + 1
NEXT i
' Remove padding
IF RIGHT$(s, 2) = "==" THEN
buffer = LEFT$(buffer, LEN(buffer) - 2)
ELSEIF RIGHT$(s, 1) = "=" THEN
buffer = LEFT$(buffer, LEN(buffer) - 1)
END IF
Base64_Decode = buffer
EXIT FUNCTION
find_index:
IF index >= 65 AND index <= 90 THEN
index = index - 65
ELSEIF index >= 97 AND index <= 122 THEN
index = index - 97 + 26
ELSEIF index >= 48 AND index <= 57 THEN
index = index - 48 + 52
ELSEIF index = 43 THEN
index = 62
ELSEIF index = 47 THEN
index = 63
END IF
RETURN
END FUNCTION
$END IF