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 164
|
#include <stdint.h>
#include <stddef.h>
#ifdef _OPENMP
#include <omp.h>
#endif
#include "libbase64.h"
#include "tables/tables.h"
#include "codecs.h"
#include "env.h"
// These static function pointers are initialized once when the library is
// first used, and remain in use for the remaining lifetime of the program.
// The idea being that CPU features don't change at runtime.
static struct codec codec = { NULL, NULL };
void
base64_stream_encode_init (struct base64_state *state, int flags)
{
// If any of the codec flags are set, redo choice:
if (codec.enc == NULL || flags & 0xFF) {
codec_choose(&codec, flags);
}
state->eof = 0;
state->bytes = 0;
state->carry = 0;
state->flags = flags;
}
void
base64_stream_encode
( struct base64_state *state
, const char *src
, size_t srclen
, char *out
, size_t *outlen
)
{
codec.enc(state, src, srclen, out, outlen);
}
void
base64_stream_encode_final
( struct base64_state *state
, char *out
, size_t *outlen
)
{
uint8_t *o = (uint8_t *)out;
if (state->bytes == 1) {
*o++ = base64_table_enc_6bit[state->carry];
*o++ = '=';
*o++ = '=';
*outlen = 3;
return;
}
if (state->bytes == 2) {
*o++ = base64_table_enc_6bit[state->carry];
*o++ = '=';
*outlen = 2;
return;
}
*outlen = 0;
}
void
base64_stream_decode_init (struct base64_state *state, int flags)
{
// If any of the codec flags are set, redo choice:
if (codec.dec == NULL || flags & 0xFFFF) {
codec_choose(&codec, flags);
}
state->eof = 0;
state->bytes = 0;
state->carry = 0;
state->flags = flags;
}
int
base64_stream_decode
( struct base64_state *state
, const char *src
, size_t srclen
, char *out
, size_t *outlen
)
{
return codec.dec(state, src, srclen, out, outlen);
}
#ifdef _OPENMP
// Due to the overhead of initializing OpenMP and creating a team of
// threads, we require the data length to be larger than a threshold:
#define OMP_THRESHOLD 20000
// Conditionally include OpenMP-accelerated codec implementations:
#include "lib_openmp.c"
#endif
void
base64_encode
( const char *src
, size_t srclen
, char *out
, size_t *outlen
, int flags
)
{
size_t s;
size_t t;
struct base64_state state;
#ifdef _OPENMP
if (srclen >= OMP_THRESHOLD) {
base64_encode_openmp(src, srclen, out, outlen, flags);
return;
}
#endif
// Init the stream reader:
base64_stream_encode_init(&state, flags);
// Feed the whole string to the stream reader:
base64_stream_encode(&state, src, srclen, out, &s);
// Finalize the stream by writing trailer if any:
base64_stream_encode_final(&state, out + s, &t);
// Final output length is stream length plus tail:
*outlen = s + t;
}
int
base64_decode
( const char *src
, size_t srclen
, char *out
, size_t *outlen
, int flags
)
{
int ret;
struct base64_state state;
#ifdef _OPENMP
if (srclen >= OMP_THRESHOLD) {
return base64_decode_openmp(src, srclen, out, outlen, flags);
}
#endif
// Init the stream reader:
base64_stream_decode_init(&state, flags);
// Feed the whole string to the stream reader:
ret = base64_stream_decode(&state, src, srclen, out, outlen);
// If when decoding a whole block, we're still waiting for input then fail:
if (ret && (state.bytes == 0)) {
return ret;
}
return 0;
}
|