35 squash_buffer_stream_init (
void* stream,
38 SquashOptions* options,
40 SquashBufferStream* s = (SquashBufferStream*) stream;
52 squash_buffer_stream_destroy (
void* stream) {
53 SquashBufferStream* s = (SquashBufferStream*) stream;
55 squash_slist_foreach ((SquashSList*) s->head, (SquashSListForeachFunc) free);
56 if (s->input != NULL) {
57 squash_buffer_free (s->input);
59 if (s->output != NULL) {
60 squash_buffer_free (s->output);
67 squash_buffer_stream_free (
void* options) {
68 squash_buffer_stream_destroy (options);
73 squash_buffer_stream_new (SquashCodec* codec,
SquashStreamType stream_type, SquashOptions* options) {
74 SquashBufferStream* stream;
76 stream = (SquashBufferStream*) malloc (
sizeof (SquashBufferStream));
77 squash_buffer_stream_init (stream, codec, stream_type, options, squash_buffer_stream_free);
83 # define MIN(a,b) (((a) < (b)) ? (a) : (b))
87 squash_buffer_stream_process (SquashBufferStream* stream) {
88 if (stream->base_object.avail_in == 0)
91 while (stream->base_object.avail_in > 0) {
92 if (stream->last_pos == SQUASH_BUFFER_STREAM_BUFFER_SIZE ||
93 stream->last == NULL) {
94 stream->last = SQUASH_SLIST_APPEND(stream->last, SquashBufferStreamSList);
97 if (stream->head == NULL) {
98 stream->head = stream->last;
102 const size_t copy_size = MIN(SQUASH_BUFFER_STREAM_BUFFER_SIZE - stream->last_pos, stream->base_object.avail_in);
103 memcpy (stream->last->data + stream->last_pos, stream->base_object.next_in, copy_size);
104 stream->base_object.next_in += copy_size;
105 stream->base_object.avail_in -= copy_size;
106 stream->last_pos += copy_size;
113 squash_buffer_stream_consolidate (SquashBufferStream* stream) {
114 if (stream->input == NULL) {
115 stream->input = squash_buffer_new (stream->base_object.total_in);
119 SquashBufferStreamSList* next;
120 SquashBufferStreamSList* list = stream->head;
122 for ( next = NULL ; list != NULL ; list = next ) {
123 next = (SquashBufferStreamSList*) list->base.next;
124 squash_buffer_append (stream->input, list->data, (next != NULL) ? SQUASH_BUFFER_STREAM_BUFFER_SIZE : stream->last_pos);
131 stream->last_pos = 0;
135 squash_buffer_stream_finish (SquashBufferStream* stream) {
138 if (stream->base_object.avail_out == 0) {
142 if (stream->input == NULL) {
143 if (stream->base_object.avail_in > 0) {
144 squash_buffer_stream_process (stream);
146 squash_buffer_stream_consolidate (stream);
148 if (stream->base_object.avail_in > 0) {
153 if (stream->output == NULL) {
154 size_t decompressed_size;
158 stream->output = squash_buffer_new (compressed_size);
160 &compressed_size, stream->output->data,
161 stream->input->length, stream->input->data,
162 stream->base_object.options);
168 stream->output->length = compressed_size;
170 if (stream->base_object.codec->impl.get_uncompressed_size != NULL) {
172 stream->output = squash_buffer_new (decompressed_size);
173 squash_buffer_set_size (stream->output, decompressed_size);
175 &decompressed_size, stream->output->data,
176 stream->input->length, stream->input->data, NULL);
186 decompressed_size = stream->input->length;
191 decompressed_size |= decompressed_size >> 1;
192 decompressed_size |= decompressed_size >> 2;
193 decompressed_size |= decompressed_size >> 4;
194 decompressed_size |= decompressed_size >> 8;
195 decompressed_size |= decompressed_size >> 16;
200 decompressed_size <<= 2;
202 stream->output = squash_buffer_new (decompressed_size);
207 if (stream->output->allocated < decompressed_size)
208 squash_buffer_clear (stream->output);
209 squash_buffer_set_size (stream->output, decompressed_size);
211 &(stream->output->length), stream->output->data,
212 stream->input->length, stream->input->data, NULL);
213 decompressed_size <<= 1;
217 squash_assert_unreachable();
221 size_t copy_size = MIN(stream->output->length - stream->base_object.total_out, stream->base_object.avail_out);
222 memcpy (stream->base_object.next_out, stream->output->data + stream->base_object.total_out, copy_size);
223 stream->base_object.next_out += copy_size;
224 stream->base_object.avail_out -= copy_size;
226 return ((stream->base_object.total_out + copy_size) == stream->output->length) ?
Performing the requested operation from the current state is not supported.
void(* SquashDestroyNotify)(void *data)
Callback to be invoked when information data is no longer needed.
Operation partially completed.
size_t squash_codec_get_uncompressed_size(SquashCodec *codec, size_t compressed_length, const uint8_t compressed[SQUASH_ARRAY_PARAM(compressed_length)])
Get the uncompressed size of the compressed buffer.
Insufficient space in buffer.
size_t squash_codec_get_max_compressed_size(SquashCodec *codec, size_t uncompressed_length)
Get the maximum buffer size necessary to store compressed data.
SquashStatus squash_codec_compress_with_options(SquashCodec *codec, size_t *compressed_length, uint8_t compressed[SQUASH_ARRAY_PARAM(*compressed_length)], size_t uncompressed_length, const uint8_t uncompressed[SQUASH_ARRAY_PARAM(uncompressed_length)], SquashOptions *options)
Compress a buffer with an existing SquashOptions.
SquashStatus squash_codec_decompress_with_options(SquashCodec *codec, size_t *decompressed_length, uint8_t decompressed[SQUASH_ARRAY_PARAM(*decompressed_length)], size_t compressed_length, const uint8_t compressed[SQUASH_ARRAY_PARAM(compressed_length)], SquashOptions *options)
Decompress a buffer with an existing SquashOptions.
void squash_stream_init(void *stream, SquashCodec *codec, SquashStreamType stream_type, SquashOptions *options, SquashDestroyNotify destroy_notify)
Initialize a stream.
SquashStatus
Status codes.
SquashStatus squash_error(SquashStatus status)
Emit an error.
void squash_stream_destroy(void *stream)
Destroy a stream.
Operation completed successfully.
SquashStreamType
Stream type.