void oggflac_metadata_callback_load_meta( const OggFLAC__StreamDecoder *decoder, const OggFLAC__StreamMetadata *metadata, void *client_data ) { OggFLAC__StreamMetadata_VorbisComment comment = metadata->data.vorbis_comment; int i; char *start, *end, *key, *value; if( metadata->type != OggFLAC__METADATA_TYPE_VORBIS_COMMENT ) { return; } for(i = 0; i < comment.num_comments; i++ ) { /* TODO: Make this faster, don't malloc start. */ int length = comment.comments[i].length; squash_malloc( start, length+1 ); memcpy( start, comment.comments[i].entry, length ); start[ length ] = '\0'; end = strchr( start, '=' ); if( end == NULL ) { continue; } key = copy_string( start, end - 1 ); value = strdup( end+1 ); insert_meta_data( client_data, NULL, key, value ); squash_free(start); } }
static SquashBZ2Stream* squash_bz2_stream_new (SquashCodec* codec, SquashStreamType stream_type, SquashOptions* options) { int bz2_e = 0; SquashBZ2Stream* stream; assert (codec != NULL); assert (stream_type == SQUASH_STREAM_COMPRESS || stream_type == SQUASH_STREAM_DECOMPRESS); stream = squash_malloc (sizeof (SquashBZ2Stream)); squash_bz2_stream_init (stream, codec, stream_type, options, squash_bz2_stream_destroy); if (stream_type == SQUASH_STREAM_COMPRESS) { bz2_e = BZ2_bzCompressInit (&(stream->stream), squash_codec_get_option_int_index (codec, options, SQUASH_BZ2_OPT_LEVEL), 0, squash_codec_get_option_int_index (codec, options, SQUASH_BZ2_OPT_WORK_FACTOR)); } else if (stream_type == SQUASH_STREAM_DECOMPRESS) { bz2_e = BZ2_bzDecompressInit (&(stream->stream), 0, squash_codec_get_option_int_index (codec, options, SQUASH_BZ2_OPT_SMALL)); } else { squash_assert_unreachable(); } if (bz2_e != BZ_OK) { /* We validate the params so OOM is really the only time this should happen, and that really shouldn't be happening here. */ stream = squash_object_unref (stream); } return stream; }
/** * @brief Open an existing stdio file with the specified options * * @warning On Windows you should not use this function unless the * code which opened the file descriptor is using the same runtime; * see http://siomsystems.com/mixing-visual-studio-versions/ for more * information. * * @param fp the stdio file to use * @param codec codec to use * @param options options * @return The opened file, or *NULL* on error * @see squash_file_steal */ SquashFile* squash_file_steal_with_options (SquashCodec* codec, FILE* fp, SquashOptions* options) { assert (fp != NULL); assert (codec != NULL); SquashFile* file = squash_malloc (sizeof (SquashFile)); if (file == NULL) return NULL; file->fp = fp; file->eof = false; file->stream = NULL; file->last_status = SQUASH_OK; file->codec = codec; file->options = (options != NULL) ? squash_object_ref (options) : NULL; #if defined(SQUASH_MMAP_IO) file->map = squash_mapped_file_empty; #endif mtx_init (&(file->mtx), mtx_recursive); SQUASH_FLOCKFILE(fp); return file; }
static SquashMSCompStream* squash_ms_stream_new (SquashCodec* codec, SquashStreamType stream_type, SquashOptions* options) { SquashMSCompStream* stream; assert (codec != NULL); assert (stream_type == SQUASH_STREAM_COMPRESS || stream_type == SQUASH_STREAM_DECOMPRESS); stream = squash_malloc (sizeof (SquashMSCompStream)); if (SQUASH_UNLIKELY(stream == NULL)) return (squash_error (SQUASH_MEMORY), NULL); squash_ms_stream_init (stream, codec, stream_type, options, squash_ms_stream_destroy); MSCompStatus status; MSCompFormat format = squash_ms_format_from_codec (codec); if (stream->base_object.stream_type == SQUASH_STREAM_COMPRESS) { status = ms_deflate_init (format, &(stream->mscomp)); } else { status = ms_inflate_init (format, &(stream->mscomp)); } if (SQUASH_UNLIKELY(status != MSCOMP_OK)) { squash_object_unref (stream); return (squash_error (squash_ms_status_to_squash_status (status)), NULL); } return stream; }
/* * Open an oggflac file * sound_format will be modified and private state information * will be returned. */ void *oggflac_open( char *filename, sound_format_t *sound_format ) { oggflac_data_t *oggflac_data; OggFLAC__StreamDecoderState state; /* Allocate space for data */ squash_malloc( oggflac_data, sizeof(oggflac_data_t) ); if( (oggflac_data->decoder = OggFLAC__stream_decoder_new()) == NULL ) { squash_free( oggflac_data ); squash_error( "Unable to create oggflac decoder" ); } if( !OggFLAC__stream_decoder_set_filename( oggflac_data->decoder, filename ) ) { squash_free( oggflac_data ); squash_error( "Unable to set filename in decoder" ); } OggFLAC__stream_decoder_set_metadata_callback( oggflac_data->decoder, oggflac_metadata_callback_decode_frame ); OggFLAC__stream_decoder_set_write_callback( oggflac_data->decoder, oggflac_write_callback_decode_frame ); OggFLAC__stream_decoder_set_error_callback( oggflac_data->decoder, oggflac_error_callback ); OggFLAC__stream_decoder_set_client_data( oggflac_data->decoder, oggflac_data ); state = OggFLAC__stream_decoder_init( oggflac_data->decoder ); switch( state ) { case OggFLAC__STREAM_DECODER_OK: /* no problem */ break; case OggFLAC__STREAM_DECODER_OGG_ERROR: case OggFLAC__STREAM_DECODER_READ_ERROR case OggFLAC__STREAM_DECODER_FLAC_STREAM_DECODER_ERROR: case OggFLAC__STREAM_DECODER_INVALID_CALLBACK: case OggFLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR: case OggFLAC__STREAM_DECODER_ALREADY_INITIALIZED: case OggFLAC__STREAM_DECODER_UNINITIALIZED: squash_free( oggflac_data ); squash_error( "Unable to initialize decoder: %s", OggFLAC__StreamDecoderStateString[ state ] ); break; } oggflac_data->buffer = NULL; oggflac_data->buffer_size = 0; oggflac_data->channels = -1; oggflac_data->sample_rate = -1; oggflac_data->duration = -1; OggFLAC__stream_decoder_process_until_end_of_metadata( oggflac_data->decoder ); sound_format->rate = oggflac_data->sample_rate; sound_format->channels = oggflac_data->channels; sound_format->bits = 16; sound_format->byte_format = SOUND_LITTLE; /* Return data */ return (void *)oggflac_data; }
static uint8_t* squash_lz4f_stream_get_output_buffer (SquashStream* stream) { SquashLZ4FStream* s = (SquashLZ4FStream*) stream; if (s->data.comp.output_buffer == NULL) s->data.comp.output_buffer = squash_malloc (squash_lz4f_stream_get_output_buffer_size (stream)); return s->data.comp.output_buffer; }
/** * @brief Initialize a stream. * @protected * * @warning This function must only be used to implement a subclass of * @ref SquashStream. Streams returned by other functions will * already be initialized, and you *must* *not* call this function on * them; doing so will likely trigger a memory leak. * * @param stream The stream to initialize. * @param codec The codec to use. * @param stream_type The stream type. * @param options The options. * @param destroy_notify Function to call to destroy the instance. * * @see squash_object_init */ void squash_stream_init (void* stream, SquashCodec* codec, SquashStreamType stream_type, SquashOptions* options, SquashDestroyNotify destroy_notify) { SquashStream* s; assert (stream != NULL); s = (SquashStream*) stream; squash_object_init (stream, false, destroy_notify); s->next_in = NULL; s->avail_in = 0; s->total_in = 0; s->next_out = NULL; s->avail_out = 0; s->total_out = 0; s->codec = codec; s->options = (options != NULL) ? squash_object_ref (options) : NULL; s->stream_type = stream_type; s->state = SQUASH_STREAM_STATE_IDLE; s->user_data = NULL; s->destroy_user_data = NULL; if (codec->impl.create_stream == NULL && codec->impl.splice != NULL) { s->priv = squash_malloc (sizeof (SquashStreamPrivate)); mtx_init (&(s->priv->io_mtx), mtx_plain); mtx_lock (&(s->priv->io_mtx)); s->priv->request = SQUASH_OPERATION_INVALID; cnd_init (&(s->priv->request_cnd)); s->priv->result = SQUASH_STATUS_INVALID; cnd_init (&(s->priv->result_cnd)); s->priv->finished = false; #if !defined(NDEBUG) int res = #endif thrd_create (&(s->priv->thread), (thrd_start_t) squash_stream_thread_func, s); assert (res == thrd_success); while (s->priv->result == SQUASH_STATUS_INVALID) cnd_wait (&(s->priv->result_cnd), &(s->priv->io_mtx)); s->priv->result = SQUASH_STATUS_INVALID; } else { s->priv = NULL; } }
static SquashBrotliStream* squash_brotli_stream_new (SquashCodec* codec, SquashStreamType stream_type, SquashOptions* options) { SquashBrotliStream* stream; assert (codec != NULL); assert (stream_type == SQUASH_STREAM_COMPRESS || stream_type == SQUASH_STREAM_DECOMPRESS); stream = (SquashBrotliStream*) squash_malloc (sizeof (SquashBrotliStream)); squash_brotli_stream_init (stream, codec, stream_type, options, squash_brotli_stream_destroy); return stream; }
/** * @brief Create a new plugin * @private * * @param name Plugin name. * @param directory Directory where the plugin is located. * @param context Context for the plugin. */ SquashPlugin* squash_plugin_new (char* name, char* directory, SquashContext* context) { SquashPlugin* plugin = (SquashPlugin*) squash_malloc (sizeof (SquashPlugin)); plugin->name = name; plugin->license = NULL; plugin->context = context; plugin->directory = directory; plugin->plugin = NULL; SQUASH_TREE_ENTRY_INIT(plugin->tree); SQUASH_TREE_INIT(&(plugin->codecs), squash_codec_compare); return plugin; }
static SquashLZ4FStream* squash_lz4f_stream_new (SquashCodec* codec, SquashStreamType stream_type, SquashOptions* options) { SquashLZ4FStream* stream; LZ4F_errorCode_t ec; assert (codec != NULL); stream = (SquashLZ4FStream*) squash_malloc (sizeof (SquashLZ4FStream)); if (SQUASH_UNLIKELY(stream == NULL)) return (squash_error (SQUASH_MEMORY), NULL); squash_lz4f_stream_init (stream, codec, stream_type, options, squash_lz4f_stream_destroy); if (stream_type == SQUASH_STREAM_COMPRESS) { ec = LZ4F_createCompressionContext(&(stream->data.comp.ctx), LZ4F_VERSION); stream->data.comp.state = SQUASH_LZ4F_STATE_INIT; stream->data.comp.output_buffer = NULL; stream->data.comp.output_buffer_pos = 0; stream->data.comp.output_buffer_size = 0; stream->data.comp.input_buffer_size = 0; stream->data.comp.prefs = (LZ4F_preferences_t) { { (LZ4F_blockSizeID_t) squash_codec_get_option_int_index (codec, options, SQUASH_LZ4F_OPT_BLOCK_SIZE), blockLinked, squash_codec_get_option_bool_index (codec, options, SQUASH_LZ4F_OPT_CHECKSUM) ? contentChecksumEnabled : noContentChecksum, }, squash_codec_get_option_int_index (codec, options, SQUASH_LZ4F_OPT_LEVEL) }; } else { ec = LZ4F_createDecompressionContext(&(stream->data.decomp.ctx), LZ4F_VERSION); } if (SQUASH_UNLIKELY(LZ4F_isError (ec))) { squash_object_unref (stream); return (squash_error (SQUASH_FAILED), NULL); } return stream; }
SquashStatus squash_file_vprintf (SquashFile* file, const char* format, va_list ap) { SquashStatus res = SQUASH_OK; int size; char* heap_buf = NULL; assert (file != NULL); assert (format != NULL); #if defined(_WIN32) size = _vscprintf (format, ap); if (HEDLEY_UNLIKELY(size < 0)) return squash_error (SQUASH_FAILED); #else char buf[256]; size = vsnprintf (buf, sizeof (buf), format, ap); if (HEDLEY_UNLIKELY(size < 0)) return squash_error (SQUASH_FAILED); else if (size >= (int) sizeof (buf)) #endif { heap_buf = squash_malloc (size + 1); if (HEDLEY_UNLIKELY(heap_buf == NULL)) return squash_error (SQUASH_MEMORY); const int written = vsnprintf (heap_buf, size + 1, format, ap); if (HEDLEY_UNLIKELY(written != size)) res = squash_error (SQUASH_FAILED); } if (HEDLEY_LIKELY(res == SQUASH_OK)) { res = squash_file_write (file, size, #if !defined(_WIN32) (heap_buf == NULL) ? (uint8_t*) buf : #endif (uint8_t*) heap_buf); } squash_free (heap_buf); return res; }
static SquashStatus squash_brieflz_compress_buffer (SquashCodec* codec, size_t* compressed_size, uint8_t compressed[HEDLEY_ARRAY_PARAM(*compressed_size)], size_t uncompressed_size, const uint8_t uncompressed[HEDLEY_ARRAY_PARAM(uncompressed_size)], SquashOptions* options) { uint8_t *dst = compressed; void *workmem = NULL; unsigned long size; #if ULONG_MAX < SIZE_MAX if (HEDLEY_UNLIKELY(ULONG_MAX < uncompressed_size) || HEDLEY_UNLIKELY(ULONG_MAX < *compressed_size)) return squash_error (SQUASH_RANGE); #endif if (HEDLEY_UNLIKELY((unsigned long) *compressed_size < squash_brieflz_get_max_compressed_size (codec, uncompressed_size))) { return squash_error (SQUASH_BUFFER_FULL); } workmem = squash_malloc (blz_workmem_size ((unsigned long) uncompressed_size)); if (HEDLEY_UNLIKELY(workmem == NULL)) { return squash_error (SQUASH_MEMORY); } size = blz_pack (uncompressed, dst, (unsigned long) uncompressed_size, workmem); squash_free (workmem); #if SIZE_MAX < ULONG_MAX if (HEDLEY_UNLIKELY(SIZE_MAX < size)) return squash_error (SQUASH_RANGE); #endif *compressed_size = (size_t) size; return SQUASH_OK; }
static char* squash_strdup_printf (const char* fmt, ...) { va_list ap; char* buf = NULL; size_t l = 0; va_start (ap, fmt); #if !defined(_WIN32) l = vsnprintf (buf, l, fmt, ap); #else l = _vscprintf (fmt, ap); #endif va_end (ap); l++; buf = squash_malloc (l); if (buf != NULL) { va_start (ap, fmt); vsnprintf(buf, l, fmt, ap); va_end (ap); } return buf; }
static void* squash_brotli_malloc (void* opaque, size_t size) { return squash_malloc (size); }
static void* squash_bsc_malloc (size_t size) { return squash_malloc (size); }
static void* squash_bz2_malloc (void* opaque, int a, int b) { return squash_malloc (((size_t) a) * ((size_t) b)); }
static void* squash_csc_alloc (void* p, size_t size) { return squash_malloc (size); }
static void* squash_density_malloc (size_t size) { return squash_malloc (size); }