tal: allow notifiers on NULL.
[ccan] / ccan / base64 / base64.h
1 /* Licensed under BSD-MIT - see LICENSE file for details */
2 #ifndef CCAN_BASE64_H
3 #define CCAN_BASE64_H
4
5 #include <stddef.h>
6 #include <stdbool.h>
7 #include <sys/types.h>
8
9 /**
10  * base64_maps_t - structure to hold maps for encode/decode
11  */
12 typedef struct {
13         char encode_map[64];
14         signed char decode_map[256];
15 } base64_maps_t;
16
17 /**
18  * base64_encoded_length - Calculate encode buffer length
19  * @param srclen the size of the data to be encoded
20  * @note add 1 to this to get null-termination
21  * @return Buffer length required for encode
22  */
23 size_t base64_encoded_length(size_t srclen);
24
25 /**
26  * base64_decoded_length - Calculate decode buffer length
27  * @param srclen Length of the data to be decoded
28  * @note This does not return the size of the decoded data!  see base64_decode
29  * @return Minimum buffer length for safe decode
30  */
31 size_t base64_decoded_length(size_t srclen);
32
33 /**
34  * base64_init_maps - populate a base64_maps_t based on a supplied alphabet
35  * @param dest A base64 maps object
36  * @param src Alphabet to populate the maps from (e.g. base64_alphabet_rfc4648)
37  */
38 void base64_init_maps(base64_maps_t *dest, const char src[64]);
39
40
41 /**
42  * base64_encode_triplet_using_maps - encode 3 bytes into base64 using a specific alphabet
43  * @param maps Maps to use for encoding (see base64_init_maps)
44  * @param dest Buffer containing 3 bytes
45  * @param src Buffer containing 4 characters
46  */
47 void base64_encode_triplet_using_maps(const base64_maps_t *maps,
48                                       char dest[4], const char src[3]);
49
50 /**
51  * base64_encode_tail_using_maps - encode the final bytes of a source using a specific alphabet
52  * @param maps Maps to use for encoding (see base64_init_maps)
53  * @param dest Buffer containing 4 bytes
54  * @param src Buffer containing srclen bytes
55  * @param srclen Number of bytes (<= 3) to encode in src
56  */
57 void base64_encode_tail_using_maps(const base64_maps_t *maps, char dest[4],
58                                    const char *src, size_t srclen);
59
60 /**
61  * base64_encode_using_maps - encode a buffer into base64 using a specific alphabet
62  * @param maps Maps to use for encoding (see base64_init_maps)
63  * @param dest Buffer to encode into
64  * @param destlen Length of dest
65  * @param src Buffer to encode
66  * @param srclen Length of the data to encode
67  * @return Number of encoded bytes set in dest. -1 on error (and errno set)
68  * @note dest will be nul-padded to destlen (past any required padding)
69  * @note sets errno = EOVERFLOW if destlen is too small
70  */
71 ssize_t base64_encode_using_maps(const base64_maps_t *maps,
72                                  char *dest, size_t destlen,
73                                  const char *src, size_t srclen);
74
75 /*
76  * base64_char_in_alphabet - returns true if character can be part of an encoded string
77  * @param maps A base64 maps object (see base64_init_maps)
78  * @param b64char Character to check
79  */
80 bool base64_char_in_alphabet(const base64_maps_t *maps, char b64char);
81
82 /**
83  * base64_decode_using_maps - decode a base64-encoded string using a specific alphabet
84  * @param maps A base64 maps object (see base64_init_maps)
85  * @param dest Buffer to decode into
86  * @param destlen length of dest
87  * @param src the buffer to decode
88  * @param srclen the length of the data to decode
89  * @return Number of decoded bytes set in dest. -1 on error (and errno set)
90  * @note dest will be nul-padded to destlen
91  * @note sets errno = EOVERFLOW if destlen is too small
92  * @note sets errno = EDOM if src contains invalid characters
93  */
94 ssize_t base64_decode_using_maps(const base64_maps_t *maps,
95                                  char *dest, size_t destlen,
96                                  const char *src, size_t srclen);
97
98 /**
99  * base64_decode_quartet_using_maps - decode 4 bytes from base64 using a specific alphabet
100  * @param maps A base64 maps object (see base64_init_maps)
101  * @param dest Buffer containing 3 bytes
102  * @param src Buffer containing 4 bytes
103  * @return Number of decoded bytes set in dest. -1 on error (and errno set)
104  * @note sets errno = EDOM if src contains invalid characters
105  */
106 int base64_decode_quartet_using_maps(const base64_maps_t *maps,
107                                      char dest[3], const char src[4]);
108
109 /**
110  * base64_decode_tail_using_maps - decode the final bytes of a base64 string using a specific alphabet
111  * @param maps A base64 maps object (see base64_init_maps)
112  * @param dest Buffer containing 3 bytes
113  * @param src Buffer containing 4 bytes - padded with '=' as required
114  * @param srclen Number of bytes to decode in src
115  * @return Number of decoded bytes set in dest. -1 on error (and errno set)
116  * @note sets errno = EDOM if src contains invalid characters
117  * @note sets errno = EINVAL if src is an invalid base64 tail
118  */
119 int base64_decode_tail_using_maps(const base64_maps_t *maps, char *dest,
120                                   const char *src, size_t srclen);
121
122
123 /* the rfc4648 functions: */
124
125 extern const base64_maps_t base64_maps_rfc4648;
126
127 /**
128  * base64_encode - Encode a buffer into base64 according to rfc4648
129  * @param dest Buffer to encode into
130  * @param destlen Length of the destination buffer
131  * @param src Buffer to encode
132  * @param srclen Length of the data to encode
133  * @return Number of encoded bytes set in dest. -1 on error (and errno set)
134  * @note dest will be nul-padded to destlen (past any required padding)
135  * @note sets errno = EOVERFLOW if destlen is too small
136  *
137  * This function encodes src according to http://tools.ietf.org/html/rfc4648
138  *
139  * Example:
140  *      size_t encoded_length;
141  *      char dest[100];
142  *      const char *src = "This string gets encoded";
143  *      encoded_length = base64_encode(dest, sizeof(dest), src, strlen(src));
144  *      printf("Returned data of length %zd @%p\n", encoded_length, &dest);
145  */
146 static inline
147 ssize_t base64_encode(char *dest, size_t destlen,
148                       const char *src, size_t srclen)
149 {
150         return base64_encode_using_maps(&base64_maps_rfc4648,
151                                         dest, destlen, src, srclen);
152 }
153
154 /**
155  * base64_encode_triplet - encode 3 bytes into base64 according to rfc4648
156  * @param dest Buffer containing 4 bytes
157  * @param src Buffer containing 3 bytes
158  */
159 static inline
160 void base64_encode_triplet(char dest[4], const char src[3])
161 {
162         base64_encode_triplet_using_maps(&base64_maps_rfc4648, dest, src);
163 }
164
165 /**
166  * base64_encode_tail - encode the final bytes of a source according to rfc4648
167  * @param dest Buffer containing 4 bytes
168  * @param src Buffer containing srclen bytes
169  * @param srclen Number of bytes (<= 3) to encode in src
170  */
171 static inline
172 void base64_encode_tail(char dest[4], const char *src, size_t srclen)
173 {
174         base64_encode_tail_using_maps(&base64_maps_rfc4648, dest, src, srclen);
175 }
176
177
178 /**
179  * base64_decode - decode An rfc4648 base64-encoded string
180  * @param dest Buffer to decode into
181  * @param destlen Length of the destination buffer
182  * @param src Buffer to decode
183  * @param srclen Length of the data to decode
184  * @return Number of decoded bytes set in dest. -1 on error (and errno set)
185  * @note dest will be nul-padded to destlen
186  * @note sets errno = EOVERFLOW if destlen is too small
187  * @note sets errno = EDOM if src contains invalid characters
188  *
189  * This function decodes the buffer according to
190  * http://tools.ietf.org/html/rfc4648
191  *
192  * Example:
193  *      size_t decoded_length;
194  *      char ret[100];
195  *      const char *src = "Zm9vYmFyYmF6";
196  *      decoded_length = base64_decode(ret, sizeof(ret), src, strlen(src));
197  *      printf("Returned data of length %zd @%p\n", decoded_length, &ret);
198  */
199 static inline
200 ssize_t base64_decode(char *dest, size_t destlen,
201                       const char *src, size_t srclen)
202 {
203         return base64_decode_using_maps(&base64_maps_rfc4648,
204                                         dest, destlen, src, srclen);
205 }
206
207 /**
208  * base64_decode_quartet - decode the first 4 characters in src into dest
209  * @param dest Buffer containing 3 bytes
210  * @param src Buffer containing 4 characters
211  * @return Number of decoded bytes set in dest. -1 on error (and errno set)
212  * @note sets errno = EDOM if src contains invalid characters
213  */
214 static inline
215 int base64_decode_quartet(char dest[3], const char src[4])
216 {
217         return base64_decode_quartet_using_maps(&base64_maps_rfc4648,
218                                                 dest, src);
219 }
220
221 /**
222  * @brief decode the final bytes of a base64 string from src into dest
223  * @param dest Buffer containing 3 bytes
224  * @param src Buffer containing 4 bytes - padded with '=' as required
225  * @param srclen Number of bytes to decode in src
226  * @return Number of decoded bytes set in dest. -1 on error (and errno set)
227  * @note sets errno = EDOM if src contains invalid characters
228  * @note sets errno = EINVAL if src is an invalid base64 tail
229  */
230 static inline
231 ssize_t base64_decode_tail(char dest[3], const char *src, size_t srclen)
232 {
233         return base64_decode_tail_using_maps(&base64_maps_rfc4648,
234                                              dest, src, srclen);
235 }
236
237 /* end rfc4648 functions */
238
239
240
241 #endif /* CCAN_BASE64_H */