File: base64.c

package info (click to toggle)
graphviz 14.0.5-2
  • links: PTS
  • area: main
  • in suites: forky, sid
  • size: 139,388 kB
  • sloc: ansic: 141,938; cpp: 11,957; python: 7,766; makefile: 4,043; yacc: 3,030; xml: 2,972; tcl: 2,495; sh: 1,388; objc: 1,159; java: 560; lex: 423; perl: 243; awk: 156; pascal: 139; php: 58; ruby: 49; cs: 31; sed: 1
file content (54 lines) | stat: -rw-r--r-- 1,556 bytes parent folder | download | duplicates (2)
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
#include <stddef.h>
#include <util/alloc.h>
#include <util/base64.h>

static size_t div_up(size_t dividend, size_t divisor) {
  return dividend / divisor + (dividend % divisor != 0);
}

static const char base64_alphabet[] =
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";

size_t gv_base64_size(size_t source_size) { return div_up(source_size, 3) * 4; }

char *gv_base64(const unsigned char *source, size_t size) {
  size_t buf_i = 0;
  char *buf = gv_alloc(gv_base64_size(size) + 1);

  for (size_t data_i = 0; data_i < size; data_i += 3) {
    unsigned char d0 = source[data_i];
    int v = (d0 & 0xFC) >> 2; // 1111_1100
    buf[buf_i++] = base64_alphabet[v];

    unsigned char d1 = data_i + 1 < size ? source[data_i + 1] : 0;
    v = (d0 & 0x03) << 4    // 0000_0011
        | (d1 & 0xF0) >> 4; // 1111_0000
    buf[buf_i++] = base64_alphabet[v];
    if (size <= data_i + 1) {
      goto end;
    }

    unsigned char d2 = data_i + 2 < size ? source[data_i + 2] : 0;
    v = (d1 & 0x0F) << 2    // 0000_1111
        | (d2 & 0xC0) >> 6; // 1100_0000
    buf[buf_i++] = base64_alphabet[v];
    if (size <= data_i + 2) {
      goto end;
    }

    v = d2 & 0x3F; // 0011_1111
    buf[buf_i++] = base64_alphabet[v];
  }

end:
  while (buf_i % 4 != 0) {
    buf[buf_i++] = base64_alphabet[64];
  }

  // Write a string terminator. This is not strictly necessary, but is a
  // backstop against callers who do not use `gv_base64_size` and assume they
  // can e.g. `fputs` the returned data.
  buf[buf_i++] = '\0';

  return buf;
}