Instrument Neutral Distributed Interface INDI  1.9.2
base64.c
Go to the documentation of this file.
1 #if 0
2  INDI
3  Copyright (C) 2003 Elwood C. Downey
4 
5  Complete rewrite of to64frombits() - gives 2x the performance
6  Complete rewrite of from64tobits_fast() - gives 3x the performance
7  Keeping from64tobits() for compatibility - gives 2.5x the performance
8  of the old implementation (Aug, 2016 by Rumen G.Bogdanovski)
9 
10  This library is free software; you can redistribute it and/or
11  modify it under the terms of the GNU Lesser General Public
12  License as published by the Free Software Foundation; either
13  version 2.1 of the License, or (at your option) any later version.
14 
15  This library is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18  Lesser General Public License for more details.
19 
20  You should have received a copy of the GNU Lesser General Public
21  License along with this library; if not, write to the Free Software
22  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 
24  Adapted from code written by Eric S. Raymond <esr@snark.thyrsus.com>
25 #endif
26 
27 /* Pair of functions to convert to/from base64.
28  * Also can be used to build a standalone utility and a loopback test.
29  * see http://www.faqs.org/rfcs/rfc3548.html
30  */
31 
37 #include <ctype.h>
38 #include <stdint.h>
39 #include "base64.h"
40 #include "base64_luts.h"
41 #include <stdio.h>
42 
43 /* convert inlen raw bytes at in to base64 string (NUL-terminated) at out.
44  * out size should be at least 4*inlen/3 + 4.
45  * return length of out (sans trailing NUL).
46  */
47 int to64frombits_s(unsigned char *out, const unsigned char *in, int inlen, size_t outlen)
48 {
49  size_t dlen = (((size_t)inlen + 2) / 3) * 4; /* 4/3, rounded up */
50 
51  if (dlen > outlen) {
52  return 0;
53  }
54 
55 #pragma GCC diagnostic push
56 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
57  return to64frombits(out, in, inlen);
58 #pragma GCC diagnostic pop
59 }
60 
61 int to64frombits(unsigned char *out, const unsigned char *in, int inlen)
62 {
63  uint16_t *b64lut = (uint16_t *)base64lut;
64  int dlen = ((inlen + 2) / 3) * 4; /* 4/3, rounded up */
65  uint16_t *wbuf = (uint16_t *)out;
66 
67  for (; inlen > 2; inlen -= 3)
68  {
69  uint32_t n = in[0] << 16 | in[1] << 8 | in[2];
70 
71  wbuf[0] = b64lut[n >> 12];
72  wbuf[1] = b64lut[n & 0x00000fff];
73 
74  wbuf += 2;
75  in += 3;
76  }
77 
78  out = (unsigned char *)wbuf;
79  if (inlen > 0)
80  {
81  unsigned char fragment;
82  *out++ = base64digits[in[0] >> 2];
83  fragment = (in[0] << 4) & 0x30;
84  if (inlen > 1)
85  fragment |= in[1] >> 4;
86  *out++ = base64digits[fragment];
87  *out++ = (inlen < 2) ? '=' : base64digits[(in[1] << 2) & 0x3c];
88  *out++ = '=';
89  }
90  *out = 0; // NULL terminate
91  return dlen;
92 }
93 
94 /* convert base64 at in to raw bytes out, returning count or <0 on error.
95  * base64 should not contain whitespaces.
96  * out should be at least 3/4 the length of in.
97  */
98 int from64tobits(char *out, const char *in)
99 {
100  char *cp = (char *)in;
101  while (*cp != 0)
102  cp += 4;
103  return from64tobits_fast(out, in, cp - in);
104 }
105 
106 int from64tobits_fast(char *out, const char *in, int inlen)
107 {
108  int outlen = 0;
109  uint8_t b1, b2, b3;
110  uint16_t s1, s2;
111  uint32_t n32;
112  int j;
113  int n = (inlen / 4) - 1;
114  uint16_t *inp = (uint16_t *)in;
115 
116  for (j = 0; j < n; j++)
117  {
118  if (in[0] == '\n')
119  in++;
120  inp = (uint16_t *)in;
121 
122  s1 = rbase64lut[inp[0]];
123  s2 = rbase64lut[inp[1]];
124 
125  n32 = s1;
126  n32 <<= 10;
127  n32 |= s2 >> 2;
128 
129  b3 = (n32 & 0x00ff);
130  n32 >>= 8;
131  b2 = (n32 & 0x00ff);
132  n32 >>= 8;
133  b1 = (n32 & 0x00ff);
134 
135  out[0] = b1;
136  out[1] = b2;
137  out[2] = b3;
138 
139  in += 4;
140  out += 3;
141  }
142  outlen = (inlen / 4 - 1) * 3;
143  if (in[0] == '\n')
144  in++;
145  inp = (uint16_t *)in;
146 
147  s1 = rbase64lut[inp[0]];
148  s2 = rbase64lut[inp[1]];
149 
150  n32 = s1;
151  n32 <<= 10;
152  n32 |= s2 >> 2;
153 
154  b3 = (n32 & 0x00ff);
155  n32 >>= 8;
156  b2 = (n32 & 0x00ff);
157  n32 >>= 8;
158  b1 = (n32 & 0x00ff);
159 
160  *out++ = b1;
161  outlen++;
162  if ((inp[1] & 0x00FF) != 0x003D)
163  {
164  *out++ = b2;
165  outlen++;
166  if ((inp[1] & 0xFF00) != 0x3D00)
167  {
168  *out++ = b3;
169  outlen++;
170  }
171  }
172  return outlen;
173 }
174 
175 #ifdef BASE64_PROGRAM
176 /* standalone program that converts to/from base64.
177  * cc -o base64 -DBASE64_PROGRAM base64.c
178  */
179 
180 #include <stdio.h>
181 #include <stdlib.h>
182 u#include <cstring>
183 
184 static void usage(char *me)
185 {
186  fprintf(stderr, "Purpose: convert stdin to/from base64 on stdout\n");
187  fprintf(stderr, "Usage: %s {-t,-f}\n", me);
188  exit(1);
189 }
190 
191 int main(int ac, char *av[])
192 {
193  int to64 = 1;
194 
195  /* decide whether to or from base64 */
196  if (ac == 2 && strcmp(av[1], "-f") == 0)
197  to64 = 0;
198  else if (ac != 1 && (ac != 2 || strcmp(av[1], "-t")))
199  usage(av[0]);
200 
201  if (to64)
202  {
203  unsigned char *rawin, *b64;
204  int i, n, nrawin, nb64;
205 
206  /* read raw on stdin until EOF */
207  rawin = malloc(4096);
208  nrawin = 0;
209  while ((n = fread(rawin + nrawin, 1, 4096, stdin)) > 0)
210  rawin = realloc(rawin, (nrawin += n) + 4096);
211 
212  /* convert to base64 */
213  b64 = malloc(4 * nrawin / 3 + 4);
214  nb64 = to64frombits(b64, rawin, nrawin);
215 
216  size_t written = 0;
217  size_t towrite = nb64;
218  while (written < nb64)
219  {
220  size_t wr = fwrite(b64 + written, 1, nb64, stdout);
221  if (wr > 0)
222  {
223  towrite -= wr;
224  written += wr;
225  }
226  }
227  }
228  else
229  {
230  unsigned char *raw, *b64;
231  int n, nraw, nb64;
232 
233  /* read base64 on stdin until EOF */
234  b64 = malloc(4096);
235  nb64 = 0;
236  while ((n = fread(b64 + nb64, 1, 4096, stdin)) > 0)
237  b64 = realloc(b64, (nb64 += n) + 4096);
238  b64[nb64] = '\0';
239 
240  /* convert to raw */
241  raw = malloc(3 * nb64 / 4);
242  nraw = from64tobits_fast(raw, b64, nb64);
243  if (nraw < 0)
244  {
245  fprintf(stderr, "base64 conversion error: %d\n", nraw);
246  return (1);
247  }
248 
249  /* write */
250  fwrite(raw, 1, nraw, stdout);
251  }
252 
253  return (0);
254 }
255 
256 #endif
257 
258 #ifdef LOOPBACK_TEST
259 /* standalone test that reads binary on stdin, converts to base64 and back,
260  * then compares. exit 0 if compares the same else 1
261  */
262 
263 #include <stdio.h>
264 #include <stdlib.h>
265 #include <cstring>
266 
267 int main(int ac, char *av[])
268 {
269  unsigned char *rawin, *b64, *rawback;
270  int n, nrawin, nrawback, nb64;
271 
272  /* read raw on stdin until EOF */
273  rawin = malloc(4096);
274  nrawin = 0;
275  while ((n = fread(rawin + nrawin, 1, 4096, stdin)) > 0)
276  rawin = realloc(rawin, (nrawin += n) + 4096);
277 
278  /* convert to base64 */
279  b64 = malloc(4 * nrawin * 3 + 4);
280  nb64 = to64frombits(b64, rawin, nrawin);
281 
282  /* convert back to raw */
283  rawback = malloc(3 * nb64 / 4);
284  nrawback = from64tobits_fast(rawback, b64, nrawin);
285  if (nrawback < 0)
286  {
287  fprintf(stderr, "base64 error: %d\n", nrawback);
288  return (1);
289  }
290  if (nrawback != nrawin)
291  {
292  fprintf(stderr, "base64 back length %d != %d\n", nrawback, nrawin);
293  return (1);
294  }
295 
296  /* compare */
297  if (memcmp(rawback, rawin, nrawin))
298  {
299  fprintf(stderr, "compare error\n");
300  return (1);
301  }
302 
303  /* success */
304  return (0);
305 }
306 #endif
to64frombits_s
int to64frombits_s(unsigned char *out, const unsigned char *in, int inlen, size_t outlen)
Convert bytes array to base64.
Definition: base64.c:47
Aux::ANY
@ ANY
Definition: celestronauxpacket.h:86
to64frombits
int to64frombits(unsigned char *out, const unsigned char *in, int inlen)
Definition: base64.c:61
base64_luts.h
base64.h
main
int main(int, char **)
Definition: tutorial_client.cpp:53
INDI
Namespace to encapsulate INDI client, drivers, and mediator classes.
Definition: AlignmentSubsystemForClients.cpp:11
me
char * me
Definition: indidriver.c:50
from64tobits_fast
int from64tobits_fast(char *out, const char *in, int inlen)
Definition: base64.c:106
from64tobits
int from64tobits(char *out, const char *in)
Convert base64 to bytes array.
Definition: base64.c:98