mirror of
https://github.com/kovidgoyal/kitty.git
synced 2026-05-29 11:18:50 +02:00
150 lines
4.4 KiB
C
Vendored
150 lines
4.4 KiB
C
Vendored
// This code makes some assumptions on the implementation of
|
|
// base64_stream_encode_init(), base64_stream_encode() and base64_stream_decode().
|
|
// Basically these assumptions boil down to that when breaking the src into
|
|
// parts, out parts can be written without side effects.
|
|
// This is met when:
|
|
// 1) base64_stream_encode() and base64_stream_decode() don't use globals;
|
|
// 2) the shared variables src and out are not read or written outside of the
|
|
// bounds of their parts, i.e. when base64_stream_encode() reads a multiple
|
|
// of 3 bytes, it must write no more then a multiple of 4 bytes, not even
|
|
// temporarily;
|
|
// 3) the state flag can be discarded after base64_stream_encode() and
|
|
// base64_stream_decode() on the parts.
|
|
|
|
static inline void
|
|
base64_encode_openmp
|
|
( const char *src
|
|
, size_t srclen
|
|
, char *out
|
|
, size_t *outlen
|
|
, int flags
|
|
)
|
|
{
|
|
size_t s;
|
|
size_t t;
|
|
size_t sum = 0, len, last_len;
|
|
struct base64_state state, initial_state;
|
|
int num_threads, i;
|
|
|
|
// Request a number of threads but not necessarily get them:
|
|
#pragma omp parallel
|
|
{
|
|
// Get the number of threads used from one thread only,
|
|
// as num_threads is a shared var:
|
|
#pragma omp single
|
|
{
|
|
num_threads = omp_get_num_threads();
|
|
|
|
// Split the input string into num_threads parts, each
|
|
// part a multiple of 3 bytes. The remaining bytes will
|
|
// be done later:
|
|
len = srclen / (num_threads * 3);
|
|
len *= 3;
|
|
last_len = srclen - num_threads * len;
|
|
|
|
// Init the stream reader:
|
|
base64_stream_encode_init(&state, flags);
|
|
initial_state = state;
|
|
}
|
|
|
|
// Single has an implicit barrier for all threads to wait here
|
|
// for the above to complete:
|
|
#pragma omp for firstprivate(state) private(s) reduction(+:sum) schedule(static,1)
|
|
for (i = 0; i < num_threads; i++)
|
|
{
|
|
// Feed each part of the string to the stream reader:
|
|
base64_stream_encode(&state, src + i * len, len, out + i * len * 4 / 3, &s);
|
|
sum += s;
|
|
}
|
|
}
|
|
|
|
// As encoding should never fail and we encode an exact multiple
|
|
// of 3 bytes, we can discard state:
|
|
state = initial_state;
|
|
|
|
// Encode the remaining bytes:
|
|
base64_stream_encode(&state, src + num_threads * len, last_len, out + num_threads * len * 4 / 3, &s);
|
|
|
|
// Finalize the stream by writing trailer if any:
|
|
base64_stream_encode_final(&state, out + num_threads * len * 4 / 3 + s, &t);
|
|
|
|
// Final output length is stream length plus tail:
|
|
sum += s + t;
|
|
*outlen = sum;
|
|
}
|
|
|
|
static inline int
|
|
base64_decode_openmp
|
|
( const char *src
|
|
, size_t srclen
|
|
, char *out
|
|
, size_t *outlen
|
|
, int flags
|
|
)
|
|
{
|
|
int num_threads, result = 0, i;
|
|
size_t sum = 0, len, last_len, s;
|
|
struct base64_state state, initial_state;
|
|
|
|
// Request a number of threads but not necessarily get them:
|
|
#pragma omp parallel
|
|
{
|
|
// Get the number of threads used from one thread only,
|
|
// as num_threads is a shared var:
|
|
#pragma omp single
|
|
{
|
|
num_threads = omp_get_num_threads();
|
|
|
|
// Split the input string into num_threads parts, each
|
|
// part a multiple of 4 bytes. The remaining bytes will
|
|
// be done later:
|
|
len = srclen / (num_threads * 4);
|
|
len *= 4;
|
|
last_len = srclen - num_threads * len;
|
|
|
|
// Init the stream reader:
|
|
base64_stream_decode_init(&state, flags);
|
|
|
|
initial_state = state;
|
|
}
|
|
|
|
// Single has an implicit barrier to wait here for the above to
|
|
// complete:
|
|
#pragma omp for firstprivate(state) private(s) reduction(+:sum, result) schedule(static,1)
|
|
for (i = 0; i < num_threads; i++)
|
|
{
|
|
int this_result;
|
|
|
|
// Feed each part of the string to the stream reader:
|
|
this_result = base64_stream_decode(&state, src + i * len, len, out + i * len * 3 / 4, &s);
|
|
sum += s;
|
|
result += this_result;
|
|
}
|
|
}
|
|
|
|
// If `result' equals `-num_threads', then all threads returned -1,
|
|
// indicating that the requested codec is not available:
|
|
if (result == -num_threads) {
|
|
return -1;
|
|
}
|
|
|
|
// If `result' does not equal `num_threads', then at least one of the
|
|
// threads hit a decode error:
|
|
if (result != num_threads) {
|
|
return 0;
|
|
}
|
|
|
|
// So far so good, now decode whatever remains in the buffer. Reuse the
|
|
// initial state, since we are at a 4-byte boundary:
|
|
state = initial_state;
|
|
result = base64_stream_decode(&state, src + num_threads * len, last_len, out + num_threads * len * 3 / 4, &s);
|
|
sum += s;
|
|
*outlen = sum;
|
|
|
|
// If when decoding a whole block, we're still waiting for input then fail:
|
|
if (result && (state.bytes == 0)) {
|
|
return result;
|
|
}
|
|
return 0;
|
|
}
|