123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150 |
- // 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;
- }
|