/** * @brief Close a file * * If @a file is a compressor the stream will finish compressing, * writing any buffered data. For codecs which do not provide a * native streaming interface, *all* of the actual compression will * take place during this call. In other words, it may block for a * non-trivial period. If this is a problem please file a bug against * Squash (including your use case), and we can discuss adding a * function call which will simply abort compression. * * In addition to freeing the @ref SquashFile instance, this function * will close the underlying *FILE* pointer. If you wish to continue * using the *FILE* for something else, use @ref squash_file_free * instead. * * @param file file to close * @return @ref SQUASH_OK on success or a negative error code on * failure */ SquashStatus squash_file_close (SquashFile* file) { FILE* fp = NULL; SquashStatus res = squash_file_free (file, &fp); if (res > SQUASH_OK) res = SQUASH_OK; if (fp != NULL) { const SquashStatus cres = HEDLEY_LIKELY(fclose (fp) == 0) ? SQUASH_OK : squash_error (SQUASH_IO); if (HEDLEY_LIKELY(res > 0)) res = cres; } return res; }
static SquashStatus squash_zling_splice (SquashCodec* codec, SquashOptions* options, SquashStreamType stream_type, SquashReadFunc read_cb, SquashWriteFunc write_cb, void* user_data) { try { SquashZlingIO stream(user_data, read_cb, write_cb); int zres = 0; if (stream_type == SQUASH_STREAM_COMPRESS) { zres = baidu::zling::Encode(&stream, &stream, NULL, squash_options_get_int_at (options, codec, SQUASH_ZLING_OPT_LEVEL)); } else { zres = baidu::zling::Decode(&stream, &stream, NULL); } if (zres == 0) return SQUASH_OK; else if (HEDLEY_LIKELY(stream.last_res < 0)) return stream.last_res; else return squash_error (SQUASH_FAILED); } catch (const std::bad_alloc& e) { return squash_error (SQUASH_MEMORY); } catch (const SquashStatus e) { return e; } catch (...) { return squash_error (SQUASH_FAILED); } HEDLEY_UNREACHABLE (); }
static SquashStatus squash_libdeflate_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) { const int level = squash_options_get_int_at (options, codec, SQUASH_LIBDEFLATE_OPT_LEVEL); struct deflate_compressor *compressor = deflate_alloc_compressor(level); *compressed_size = deflate_compress(compressor, uncompressed, uncompressed_size, compressed, *compressed_size); deflate_free_compressor(compressor); return HEDLEY_LIKELY(*compressed_size != 0) ? SQUASH_OK : squash_error (SQUASH_BUFFER_FULL); }
extern "C" SquashStatus squash_plugin_init_codec (SquashCodec* codec, SquashCodecImpl* impl) { const char* name = squash_codec_get_name (codec); if (HEDLEY_LIKELY(strcmp ("zling", name) == 0)) { impl->options = squash_zling_options; impl->splice = squash_zling_splice; impl->get_max_compressed_size = squash_zling_get_max_compressed_size; } else { return squash_error (SQUASH_UNABLE_TO_LOAD); } return SQUASH_OK; }
extern "C" SquashStatus squash_plugin_init_codec (SquashCodec* codec, SquashCodecImpl* impl) { const char* name = squash_codec_get_name (codec); if (HEDLEY_LIKELY(strcmp ("yalz77", name) == 0)) { impl->options = squash_yalz77_options; impl->get_max_compressed_size = squash_yalz77_get_max_compressed_size; impl->decompress_buffer = squash_yalz77_decompress_buffer; impl->compress_buffer = squash_yalz77_compress_buffer; } else { return SQUASH_UNABLE_TO_LOAD; } return SQUASH_OK; }
SquashStatus squash_plugin_init_codec (SquashCodec* codec, SquashCodecImpl* impl) { const char* name = squash_codec_get_name (codec); if (HEDLEY_LIKELY(strcmp ("deflate", name) == 0)) { impl->options = squash_libdeflate_options; impl->get_max_compressed_size = squash_libdeflate_get_max_compressed_size; impl->decompress_buffer = squash_libdeflate_decompress_buffer; impl->compress_buffer = squash_libdeflate_compress_buffer; } else { return squash_error (SQUASH_UNABLE_TO_LOAD); } return SQUASH_OK; }
SquashStatus squash_plugin_init_lz4f (SquashCodec* codec, SquashCodecImpl* impl) { const char* name = squash_codec_get_name (codec); if (HEDLEY_LIKELY(strcmp ("lz4", name) == 0)) { impl->info = SQUASH_CODEC_INFO_CAN_FLUSH; impl->options = squash_lz4f_options; impl->get_max_compressed_size = squash_lz4f_get_max_compressed_size; impl->create_stream = squash_lz4f_create_stream; impl->process_stream = squash_lz4f_process_stream; } else { return SQUASH_UNABLE_TO_LOAD; } return SQUASH_OK; }
SquashStatus squash_plugin_init_codec (SquashCodec* codec, SquashCodecImpl* impl) { const char* name = squash_codec_get_name (codec); if (HEDLEY_LIKELY(strcmp ("brieflz", name) == 0)) { impl->info = SQUASH_CODEC_INFO_WRAP_SIZE; /* impl->get_uncompressed_size = squash_brieflz_get_uncompressed_size; */ impl->get_max_compressed_size = squash_brieflz_get_max_compressed_size; impl->decompress_buffer = squash_brieflz_decompress_buffer; impl->compress_buffer_unsafe = squash_brieflz_compress_buffer; } else { return squash_error (SQUASH_UNABLE_TO_LOAD); } return SQUASH_OK; }
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; }
SquashStatus squash_plugin_init_codec (SquashCodec* codec, SquashCodecImpl* impl) { bsc_init_full (LIBBSC_DEFAULT_FEATURES, squash_bsc_malloc, squash_bsc_zero_malloc, squash_bsc_free); const char* name = squash_codec_get_name (codec); if (HEDLEY_LIKELY(strcmp ("bsc", name) == 0)) { impl->options = squash_bsc_options; impl->get_uncompressed_size = squash_bsc_get_uncompressed_size; impl->get_max_compressed_size = squash_bsc_get_max_compressed_size; impl->decompress_buffer = squash_bsc_decompress_buffer; impl->compress_buffer_unsafe = squash_bsc_compress_buffer_unsafe; } else { return squash_error (SQUASH_UNABLE_TO_LOAD); } return SQUASH_OK; }
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; }
/** * @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 (HEDLEY_LIKELY(object->destroy_notify != NULL)) object->destroy_notify (obj); squash_free (obj); return NULL; } else { return NULL; } }