190 squash_stream_thread_func (SquashStream* stream) {
191 SquashStreamPrivate* priv = stream->priv;
194 mtx_lock (&(priv->io_mtx));
196 cnd_signal (&(priv->result_cnd));
198 while ((operation = priv->request) == SQUASH_OPERATION_INVALID) {
199 cnd_wait (&(priv->request_cnd), &(priv->io_mtx));
201 priv->request = SQUASH_OPERATION_INVALID;
203 priv->result = stream->codec->impl.process_stream (stream, operation);
204 priv->finished =
true;
205 cnd_signal (&(priv->result_cnd));
206 mtx_unlock (&(priv->io_mtx));
224 SquashStreamPrivate* priv = stream->priv;
227 priv->result = status;
228 cnd_signal (&(priv->result_cnd));
229 mtx_unlock (&(priv->io_mtx));
233 mtx_lock (&(priv->io_mtx));
234 while ((operation = priv->request) == SQUASH_OPERATION_INVALID) {
235 cnd_wait (&(priv->request_cnd), &(priv->io_mtx));
237 priv->request = SQUASH_OPERATION_INVALID;
242 squash_stream_send_to_thread (SquashStream* stream,
SquashOperation operation) {
243 SquashStreamPrivate* priv = stream->priv;
246 priv->request = operation;
247 cnd_signal (&(priv->request_cnd));
248 mtx_unlock (&(priv->io_mtx));
250 mtx_lock (&(priv->io_mtx));
251 while ((result = priv->result) == SQUASH_STATUS_INVALID) {
252 cnd_wait (&(priv->result_cnd), &(priv->io_mtx));
254 priv->result = SQUASH_STATUS_INVALID;
256 if (priv->finished ==
true) {
257 mtx_unlock (&(priv->io_mtx));
258 thrd_join (priv->thread, NULL);
280 SquashOptions* options,
284 assert (stream != NULL);
286 s = (SquashStream*) stream;
300 s->stream_type = stream_type;
301 s->state = SQUASH_STREAM_STATE_IDLE;
304 s->destroy_user_data = NULL;
307 s->priv = malloc (
sizeof (SquashStreamPrivate));
309 mtx_init (&(s->priv->io_mtx), mtx_plain);
310 mtx_lock (&(s->priv->io_mtx));
312 s->priv->request = SQUASH_OPERATION_INVALID;
313 cnd_init (&(s->priv->request_cnd));
315 s->priv->result = SQUASH_STATUS_INVALID;
316 cnd_init (&(s->priv->result_cnd));
318 s->priv->finished =
false;
322 thrd_create (&(s->priv->thread), (thrd_start_t) squash_stream_thread_func, s);
323 assert (res == thrd_success);
325 while (s->priv->result == SQUASH_STATUS_INVALID)
326 cnd_wait (&(s->priv->result_cnd), &(s->priv->io_mtx));
327 s->priv->result = SQUASH_STATUS_INVALID;
345 assert (stream != NULL);
347 s = (SquashStream*) stream;
349 if (SQUASH_UNLIKELY(s->priv != NULL)) {
350 SquashStreamPrivate* priv = (SquashStreamPrivate*) s->priv;
352 if (!priv->finished) {
355 cnd_destroy (&(priv->request_cnd));
356 cnd_destroy (&(priv->result_cnd));
357 mtx_destroy (&(priv->io_mtx));
362 if (s->destroy_user_data != NULL && s->user_data != NULL) {
363 s->destroy_user_data (s->user_data);
366 if (s->options != NULL) {
385 va_list options_list;
386 SquashStream* stream;
388 va_start (options_list, stream_type);
390 va_end (options_list);
408 SquashCodec* codec_real;
411 if (codec_real == NULL) {
435 const char*
const* keys,
436 const char*
const* values) {
451 SquashOptions* options) {
452 SquashCodec* codec_real;
454 assert (codec != NULL);
458 return (codec_real != NULL) ?
474 assert (codec != NULL);
476 va_list options_list;
479 va_start (options_list, stream_type);
481 va_end (options_list);
497 SquashOptions* options) {
502 squash_stream_process_internal (SquashStream* stream,
SquashOperation operation) {
504 SquashCodecImpl* impl = NULL;
507 SquashStreamPrivate* priv = (SquashStreamPrivate*) stream->priv;
509 assert (stream != NULL);
510 codec = stream->codec;
511 assert (codec != NULL);
513 assert (impl != NULL);
545 switch (stream->state) {
546 case SQUASH_STREAM_STATE_IDLE:
547 case SQUASH_STREAM_STATE_RUNNING:
550 case SQUASH_STREAM_STATE_FLUSHING:
553 case SQUASH_STREAM_STATE_FINISHING:
556 case SQUASH_STREAM_STATE_FINISHED:
561 if (current_operation > operation) {
565 const size_t avail_in = stream->avail_in;
566 const size_t avail_out = stream->avail_out;
592 uint8_t* next_out = NULL;
593 uint8_t output_sbb = 0;
594 if (stream->avail_out == 0) {
595 next_out = stream->next_out;
596 stream->avail_out = 1;
597 stream->next_out = &output_sbb;
600 while (current_operation <= operation) {
603 if (stream->avail_in == 0 && stream->state == SQUASH_STREAM_STATE_IDLE) {
606 res = squash_stream_send_to_thread (stream, current_operation);
607 }
else if (impl->process_stream != NULL) {
608 res = impl->process_stream (stream, current_operation);
610 res = squash_buffer_stream_process ((SquashBufferStream*) stream);
614 if (current_operation == operation) {
617 res = squash_stream_send_to_thread (stream, current_operation);
618 }
else if (impl->process_stream == NULL) {
621 res = impl->process_stream (stream, current_operation);
634 if (impl->process_stream != NULL) {
636 if (!(priv->finished))
637 res = squash_stream_send_to_thread (stream, current_operation);
639 res = impl->process_stream (stream, current_operation);
642 res = squash_buffer_stream_finish ((SquashBufferStream*) stream);
655 if (stream->avail_out == 0) {
661 switch (current_operation) {
663 stream->state = SQUASH_STREAM_STATE_RUNNING;
666 stream->state = SQUASH_STREAM_STATE_FLUSHING;
669 stream->state = SQUASH_STREAM_STATE_FINISHING;
672 squash_assert_unreachable ();
677 stream->state = SQUASH_STREAM_STATE_FINISHED;
681 stream->state = SQUASH_STREAM_STATE_IDLE;
689 stream->avail_out = 0;
690 stream->next_out = next_out;
693 stream->total_in += (avail_in - stream->avail_in);
694 stream->total_out += (avail_out - stream->avail_out);
SquashStream * squash_codec_create_stream_with_options(SquashCodec *codec, SquashStreamType stream_type, SquashOptions *options)
Create a new stream with existing SquashOptions.
Performing the requested operation from the current state is not supported.
The requested operation is not available.
SquashStatus squash_stream_finish(SquashStream *stream)
Finish writing to a stream.
SquashOperation squash_stream_yield(SquashStream *stream, SquashStatus status)
Yield execution back to the main thread.
SquashCodec * squash_get_codec(const char *codec)
Retrieve a SquashCodec.
SquashStream * squash_stream_new_codec(SquashCodec *codec, SquashStreamType stream_type,...)
Create a new stream using a codec instance.
void(* SquashDestroyNotify)(void *data)
Callback to be invoked when information data is no longer needed.
The data is processed in a background thread.
Reached the end of the stream while decoding.
SquashStream * squash_stream_newa(const char *codec, SquashStreamType stream_type, const char *const *keys, const char *const *values)
Create a new stream with key/value option arrays.
Operation partially completed.
SquashOptions * squash_options_newv(SquashCodec *codec, va_list options)
Create a new group of options from a variadic list.
SquashStream * squash_stream_new_codec_with_options(SquashCodec *codec, SquashStreamType stream_type, SquashOptions *options)
Create a new stream using codec and options intances.
SquashCodecImpl * squash_codec_get_impl(SquashCodec *codec)
Get the codec's function table.
Insufficient space in buffer.
Continue processing the stream normally.
void * squash_object_unref(void *obj)
Decrement the reference count on an object.
SquashStream * squash_stream_newv(const char *codec, SquashStreamType stream_type, va_list options)
Create a new stream with a variadic list of options.
SquashStatus squash_stream_flush(SquashStream *stream)
Flush a stream.
void squash_stream_init(void *stream, SquashCodec *codec, SquashStreamType stream_type, SquashOptions *options, SquashDestroyNotify destroy_notify)
Initialize a stream.
SquashStatus
Status codes.
SquashStream * squash_stream_new_with_options(const char *codec, SquashStreamType stream_type, SquashOptions *options)
Create a new stream with options.
SquashOperation
Operations to perform on a stream.
SquashStatus squash_error(SquashStatus status)
Emit an error.
void squash_stream_destroy(void *stream)
Destroy a stream.
void * squash_object_ref(void *obj)
Increment the reference count on an object.
SquashStream * squash_stream_new(const char *codec, SquashStreamType stream_type,...)
Create a new stream.
SquashStatus squash_stream_process(SquashStream *stream)
Process a stream.
Finish processing the stream.
Operation completed successfully.
void squash_object_destroy(void *obj)
Destroy an object.
SquashStreamType
Stream type.
void squash_object_init(void *obj, bool is_floating, SquashDestroyNotify destroy_notify)
Initialize a new object.