Exemple #1
0
static
#endif
SquashFile*
squash_file_wopen_with_options (SquashCodec* codec, const wchar_t* filename, const wchar_t* mode, SquashOptions* options) {
  assert (codec != NULL);
  assert (filename != NULL);
  assert (mode != NULL);

#if !defined(_WIN32)
  char* nfilename = squash_charset_wide_to_utf8 (filename);
  if (nfilename == NULL)
    return NULL;

  char* nmode = squash_charset_wide_to_utf8 (mode);
  if (nmode == NULL) {
    squash_free (nfilename);
    return NULL;
  }

  SquashFile* file = squash_file_open_with_options (codec, nfilename, nmode, options);
  squash_free (nfilename);
  squash_free (nmode);
  return file;
#else
  FILE* fp = _wfopen (filename, mode);
  if (HEDLEY_UNLIKELY(fp == NULL))
    return NULL;

  return squash_file_steal_with_options (codec, fp, options);
#endif
}
Exemple #2
0
/**
 * @brief Open a file using a with the specified options
 *
 * @a filename is assumed to be UTF-8 encoded.  On Windows, this
 * function will call @ref squash_file_wopen_with_options internally.
 * On other platforms, filenames on disk are assumed to be in UTF-8
 * format, therefore the @a filename is passed through to `fopen`
 * without any conversion.
 *
 * @param filename name of the file to open
 * @param mode file mode
 * @param codec codec to use
 * @param options options
 * @return The opened file, or *NULL* on error
 * @see squash_file_open
 * @see squash_file_wopen_with_options
 */
SquashFile*
squash_file_open_with_options (SquashCodec* codec, const char* filename, const char* mode, SquashOptions* options) {
  assert (filename != NULL);
  assert (mode != NULL);
  assert (codec != NULL);

#if !defined(_WIN32)
  FILE* fp = fopen (filename, mode);
  if (HEDLEY_UNLIKELY(fp == NULL))
    return NULL;

  return squash_file_steal_with_options (codec, fp, options);
#else
  wchar_t* wfilename = squash_charset_utf8_to_wide (filename);
  if (wfilename == NULL)
    return NULL;

  wchar_t* wmode = squash_charset_utf8_to_wide (mode);
  if (wmode == NULL) {
    squash_free (wfilename);
    return NULL;
  }

  SquashFile* file = squash_file_wopen_with_options (codec, wfilename, wmode, options);
  squash_free (wfilename);
  squash_free (wmode);
  return file;
#endif
}
Exemple #3
0
/*
 * 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;
}
Exemple #4
0
/*
 * Close the opened song.
 */
void oggflac_close( void *data ) {
    oggflac_data_t *oggflac_data = (oggflac_data_t *)data;

    OggFLAC__stream_decoder_finish( oggflac_data->decoder );

    OggFLAC__stream_decoder_delete( oggflac_data->decoder );

    /* Free allocated storage */
    squash_free( oggflac_data->buffer );
    oggflac_data->buffer_size = 0;
    squash_free( oggflac_data );

    return;
}
Exemple #5
0
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);
    }
}
Exemple #6
0
/**
 * @brief Destroy a stream.
 * @protected
 *
 * @warning This function must only be used to implement a subclass of
 * @ref SquashObject.  Each subclass should implement a *_destroy
 * function which should perform any operations needed to destroy
 * their own data and chain up to the *_destroy function of the base
 * class, eventually invoking ::squash_object_destroy.  Invoking this
 * function in any other context is likely to cause a memory leak or
 * crash.  If you are not creating a subclass, you should be calling
 * @ref squash_object_unref instead.
 *
 * @param stream The stream.
 *
 * @see squash_object_destroy
 */
void
squash_stream_destroy (void* stream) {
    SquashStream* s;

    assert (stream != NULL);

    s = (SquashStream*) stream;

    if (SQUASH_UNLIKELY(s->priv != NULL)) {
        SquashStreamPrivate* priv = (SquashStreamPrivate*) s->priv;

        if (!priv->finished) {
            squash_stream_send_to_thread (s, SQUASH_OPERATION_TERMINATE);
        }
        cnd_destroy (&(priv->request_cnd));
        cnd_destroy (&(priv->result_cnd));
        mtx_destroy (&(priv->io_mtx));

        squash_free (s->priv);
    }

    if (s->destroy_user_data != NULL && s->user_data != NULL) {
        s->destroy_user_data (s->user_data);
    }

    if (s->options != NULL) {
        s->options = squash_object_unref (s->options);
    }

    squash_object_destroy (stream);
}
Exemple #7
0
/**
 * @brief Free a file
 *
 * This function will free the @ref SquashFile, but unlike @ref
 * squash_file_close it will not actually close the underlying *FILE*
 * pointer.  Instead, it will return the value in the @a fp argument,
 * allowing you to further manipulate it.
 *
 * @warning On Windows you should not use this function unless Squash
 * is linked against the same runtime as the code you want to continue
 * using the file pointer from; see
 * http://siomsystems.com/mixing-visual-studio-versions/ for more
 * information.
 *
 * @param file file to free
 * @param[out] fp location to store the underlying *FILE* pointer
 * @return @ref SQUASH_OK on success or a negative error code on
 *   failure
 */
SquashStatus
squash_file_free (SquashFile* file, FILE** fp) {
  SquashStatus res = SQUASH_OK;

  if (HEDLEY_UNLIKELY(file == NULL)) {
    if (fp != NULL)
      *fp = NULL;
    return SQUASH_OK;
  }

  squash_file_lock (file);

  if (file->stream != NULL && file->stream->stream_type == SQUASH_STREAM_COMPRESS)
    res = squash_file_write_internal (file, 0, NULL, SQUASH_OPERATION_FINISH);

#if defined(SQUASH_MMAP_IO)
  squash_mapped_file_destroy (&(file->map), false);
#endif

  if (fp != NULL)
    *fp = file->fp;

  SQUASH_FUNLOCKFILE(file->fp);

  squash_object_unref (file->stream);
  squash_object_unref (file->options);

  squash_file_unlock (file);

  mtx_destroy (&(file->mtx));

  squash_free (file);

  return res;
}
Exemple #8
0
static void
squash_lz4f_stream_destroy (void* stream) {
  SquashLZ4FStream* s = (SquashLZ4FStream*) stream;

  if (((SquashStream*) stream)->stream_type == SQUASH_STREAM_COMPRESS) {
    LZ4F_freeCompressionContext(s->data.comp.ctx);

    if (s->data.comp.output_buffer != NULL)
      squash_free (s->data.comp.output_buffer);
  } else {
    LZ4F_freeDecompressionContext(s->data.decomp.ctx);
  }

  squash_stream_destroy (stream);
}
Exemple #9
0
static
#endif
SquashStatus
squash_file_vwprintf (SquashFile* file,
                      const wchar_t* format,
                      va_list ap) {
  SquashStatus res = SQUASH_OK;
  int size;
  wchar_t* buf = NULL;

  assert (file != NULL);
  assert (format != NULL);

  size = _vscwprintf (format, ap);
  if (HEDLEY_UNLIKELY(size < 0))
    return squash_error (SQUASH_FAILED);

  buf = calloc (size + 1, sizeof (wchar_t));
  if (HEDLEY_UNLIKELY(buf == NULL))
    return squash_error (SQUASH_MEMORY);

#if !defined(_WIN32)
  const int written = vswprintf (buf, size + 1, format, ap);
#else
  const int written = _vsnwprintf (buf, size + 1, format, ap);
#endif
  if (HEDLEY_UNLIKELY(written != size)) {
    res = squash_error (SQUASH_FAILED);
  } else {
    size_t data_size;
    char* data;
    bool conv_success =
      squash_charset_convert (&data_size, &data, "UTF-8",
                              size * sizeof(wchar_t), (char*) buf, squash_charset_get_wide ());

    if (HEDLEY_LIKELY(conv_success))
      res = squash_file_write (file, data_size, (uint8_t*) data);
    else
      res = squash_error (SQUASH_FAILED);
  }

  squash_free (buf);

  return res;
}
Exemple #10
0
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;
}
Exemple #11
0
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;
}
Exemple #12
0
/**
 * @brief Decrement the reference count on an object.
 *
 * Once the reference count reaches 0 the object will be freed.
 *
 * @param obj The object to decrease the reference count of.
 * @return NULL
 */
void*
squash_object_unref (void* obj) {
  if (obj == NULL)
    return NULL;

  SquashObject* object = (SquashObject*) obj;

  unsigned int ref_count = squash_atomic_dec (&(object->ref_count));

  if (ref_count == 1) {
    if (SQUASH_LIKELY(object->destroy_notify != NULL))
      object->destroy_notify (obj);

    squash_free (obj);

    return NULL;
  } else {
    return NULL;
  }
}
Exemple #13
0
static SquashStatus
squash_lzg_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) {
  lzg_encoder_config_t cfg = {
    squash_options_get_int_at (options, codec, SQUASH_LZG_OPT_LEVEL),
    squash_options_get_bool_at (options, codec, SQUASH_LZG_OPT_FAST),
    NULL,
    NULL
  };

#if UINT32_MAX < SIZE_MAX
  if (HEDLEY_UNLIKELY(UINT32_MAX < uncompressed_size) ||
      HEDLEY_UNLIKELY(UINT32_MAX < *compressed_size))
    return squash_error (SQUASH_RANGE);
#endif

  uint8_t* workmem = squash_calloc (LZG_WorkMemSize (&cfg), 1);
  if (HEDLEY_UNLIKELY(workmem == NULL))
    return squash_error (SQUASH_MEMORY);
  lzg_uint32_t res = LZG_EncodeFull ((const unsigned char*) uncompressed, (lzg_uint32_t) uncompressed_size,
                                     (unsigned char*) compressed, (lzg_uint32_t) *compressed_size,
                                     &cfg, workmem);
  squash_free (workmem);

  if (res == 0) {
    return squash_error (SQUASH_FAILED);
  } else {
#if SIZE_MAX < UINT32_MAX
    if (HEDLEY_UNLIKELY(SIZE_MAX < res))
      return squash_error (SQUASH_RANGE);
#endif
    *compressed_size = (size_t) res;
    return SQUASH_OK;
  }
}
Exemple #14
0
static void
squash_brotli_free (void* opaque, void* ptr) {
  squash_free (ptr);
}
Exemple #15
0
static void squash_bsc_free (void* ptr) {
  squash_free (ptr);
}
Exemple #16
0
/**
 * @brief load a %SquashPlugin
 *
 * @note This function is generally only useful inside of a callback
 * passed to ::squash_foreach_plugin.  Every other way to get a plugin
 * (such as ::squash_get_plugin) will initialize the plugin as well
 * (and return *NULL* instead of the plugin if initialization fails).
 * The foreach functions, however, do not initialize the plugin since
 * doing so requires actually loading the plugin.
 *
 * @param plugin The plugin to load.
 * @return A status code.
 * @retval SQUASH_OK The plugin has been loaded.
 * @retval SQUASH_UNABLE_TO_LOAD Unable to load plugin.
 */
SquashStatus
squash_plugin_init (SquashPlugin* plugin) {
    if (plugin->plugin == NULL) {
#if !defined(_WIN32)
        void* handle;
#else
        HMODULE handle;
#endif
        char* plugin_file_name;

        plugin_file_name = squash_strdup_printf ("%s/%ssquash%s-plugin-%s%s", plugin->directory, SQUASH_SHARED_LIBRARY_PREFIX, SQUASH_VERSION_API, plugin->name, SQUASH_SHARED_LIBRARY_SUFFIX);
        if (plugin_file_name == NULL)
            return squash_error (SQUASH_MEMORY);

#if !defined(_WIN32)
        handle = dlopen (plugin_file_name, RTLD_LAZY);
#else
        handle = LoadLibrary (TEXT(plugin_file_name));
        if (handle == NULL) {
            squash_free (plugin_file_name);
#if defined(_DEBUG)
            plugin_file_name = squash_strdup_printf ("%s/Debug/%ssquash%s-plugin-%s%s", plugin->directory, SQUASH_SHARED_LIBRARY_PREFIX, SQUASH_VERSION_API, plugin->name, SQUASH_SHARED_LIBRARY_SUFFIX);
#else
            plugin_file_name = squash_strdup_printf ("%s/Release/%ssquash%s-plugin-%s%s", plugin->directory, SQUASH_SHARED_LIBRARY_PREFIX, SQUASH_VERSION_API, plugin->name, SQUASH_SHARED_LIBRARY_SUFFIX);
#endif
            handle = LoadLibrary (TEXT(plugin_file_name));
        }
#endif

        squash_free (plugin_file_name);

        if (SQUASH_LIKELY(handle != NULL)) {
            SQUASH_MTX_LOCK(plugin_init);
            if (plugin->plugin == NULL) {
                plugin->plugin = handle;
                handle = NULL;
            }
            SQUASH_MTX_UNLOCK(plugin_init);
        } else {
            return squash_error (SQUASH_UNABLE_TO_LOAD);
        }

        if (handle != NULL) {
#if !defined(_WIN32)
            dlclose (handle);
#else
            FreeLibrary (handle);
#endif
        } else {
            SquashStatus (*init_func) (SquashPlugin*);
#if !defined(_WIN32)
            *(void **) (&init_func) = dlsym (plugin->plugin, "squash_plugin_init_plugin");
#else
            *(void **) (&init_func) = GetProcAddress (plugin->plugin, "squash_plugin_init_plugin");
#endif
            if (init_func != NULL) {
                init_func (plugin);
            }
        }
    }

    return SQUASH_LIKELY(plugin->plugin != NULL) ? SQUASH_OK : squash_error (SQUASH_UNABLE_TO_LOAD);
}
Exemple #17
0
static void squash_csc_free (void* p, void* address) {
  squash_free (address);
}
Exemple #18
0
static void
squash_density_free (void* ptr) {
  squash_free (ptr);
}