@@ -103,16 +103,79 @@ f_bytevector_base64_decode (s7_scheme* sc, s7_pointer args) {
103103 return out;
104104}
105105
106+ static s7_pointer
107+ f_bytevector_base64_encode (s7_scheme* sc, s7_pointer args) {
108+ s7_pointer arg= s7_car (args);
109+
110+ if (!s7_is_byte_vector (arg)) {
111+ return base64_error (sc, " bytevector-base64-encode" , " type-error" ,
112+ " bytevector-base64-encode: input must be bytevector" , arg);
113+ }
114+
115+ s7_int in_len= s7_integer (s7_cadr (args));
116+ uint8_t * in = (uint8_t *) s7_byte_vector_elements (arg);
117+
118+ static const uint8_t encode_table[64 ]= {
119+ ' A' , ' B' , ' C' , ' D' , ' E' , ' F' , ' G' , ' H' , ' I' , ' J' , ' K' , ' L' , ' M' , ' N' , ' O' , ' P' , ' Q' , ' R' , ' S' , ' T' , ' U' , ' V' ,
120+ ' W' , ' X' , ' Y' , ' Z' , ' a' , ' b' , ' c' , ' d' , ' e' , ' f' , ' g' , ' h' , ' i' , ' j' , ' k' , ' l' , ' m' , ' n' , ' o' , ' p' , ' q' , ' r' ,
121+ ' s' , ' t' , ' u' , ' v' , ' w' , ' x' , ' y' , ' z' , ' 0' , ' 1' , ' 2' , ' 3' , ' 4' , ' 5' , ' 6' , ' 7' , ' 8' , ' 9' , ' +' , ' /' };
122+
123+ const uint8_t PAD = (uint8_t ) ' =' ;
124+
125+ s7_int out_len= (in_len == 0 ) ? 0 : 4 * ((in_len + 2 ) / 3 );
126+ s7_pointer out = s7_make_byte_vector (sc, out_len, 1 , NULL );
127+ uint8_t * out_buf= (uint8_t *) s7_byte_vector_elements (out);
128+
129+ s7_int i= 0 ;
130+ s7_int j= 0 ;
131+
132+ while (i + 2 < in_len) {
133+ uint32_t triple= ((uint32_t ) in[i] << 16 ) | ((uint32_t ) in[i + 1 ] << 8 ) | in[i + 2 ];
134+ out_buf[j] = encode_table[(triple >> 18 ) & 0x3F ];
135+ out_buf[j + 1 ] = encode_table[(triple >> 12 ) & 0x3F ];
136+ out_buf[j + 2 ] = encode_table[(triple >> 6 ) & 0x3F ];
137+ out_buf[j + 3 ] = encode_table[triple & 0x3F ];
138+ i+= 3 ;
139+ j+= 4 ;
140+ }
141+
142+ s7_int rem= in_len - i;
143+ if (rem == 1 ) {
144+ uint32_t triple= (uint32_t ) in[i] << 16 ;
145+ out_buf[j] = encode_table[(triple >> 18 ) & 0x3F ];
146+ out_buf[j + 1 ] = encode_table[(triple >> 12 ) & 0x3F ];
147+ out_buf[j + 2 ] = PAD ;
148+ out_buf[j + 3 ] = PAD ;
149+ }
150+ else if (rem == 2 ) {
151+ uint32_t triple= ((uint32_t ) in[i] << 16 ) | ((uint32_t ) in[i + 1 ] << 8 );
152+ out_buf[j] = encode_table[(triple >> 18 ) & 0x3F ];
153+ out_buf[j + 1 ] = encode_table[(triple >> 12 ) & 0x3F ];
154+ out_buf[j + 2 ] = encode_table[(triple >> 6 ) & 0x3F ];
155+ out_buf[j + 3 ] = PAD ;
156+ }
157+
158+ return out;
159+ }
160+
106161static void
107162glue_bytevector_base64_decode (s7_scheme* sc) {
108163 const char * name= " g_bytevector-base64-decode" ;
109164 const char * desc= " (g_bytevector-base64-decode bv len) => bytevector" ;
110165 s7_define_function (sc, name, f_bytevector_base64_decode, 2 , 0 , false , desc);
111166}
112167
168+ static void
169+ glue_bytevector_base64_encode (s7_scheme* sc) {
170+ const char * name= " g_bytevector-base64-encode" ;
171+ const char * desc= " (g_bytevector-base64-encode bv len) => bytevector" ;
172+ s7_define_function (sc, name, f_bytevector_base64_encode, 2 , 0 , false , desc);
173+ }
174+
113175void
114176glue_liii_base64 (s7_scheme* sc) {
115177 glue_bytevector_base64_decode (sc);
178+ glue_bytevector_base64_encode (sc);
116179}
117180
118181} // namespace goldfish
0 commit comments