From: Eric Biggers Date: Sat, 25 Apr 2015 20:00:07 +0000 (-0500) Subject: Clean up setting of compression type X-Git-Tag: v1.8.1~41 X-Git-Url: https://wimlib.net/git/?p=wimlib;a=commitdiff_plain;h=1855a4637636e8b00ff30fdbee6d2628de73381a Clean up setting of compression type - Use the enum instead of an int - Consolidate the per-compression-type information into an array --- diff --git a/include/wimlib.h b/include/wimlib.h index 9988d254..e702fc3b 100644 --- a/include/wimlib.h +++ b/include/wimlib.h @@ -2603,10 +2603,9 @@ wimlib_add_tree(WIMStruct *wim, int image, * an on-disk file. * * @param ctype - * The "output compression type" to assign to the ::WIMStruct, given as one - * of the ::wimlib_compression_type values. This is the compression type - * that will be used if the ::WIMStruct is later persisted to an on-disk - * file using wimlib_write(). + * The "output compression type" to assign to the ::WIMStruct. This is the + * compression type that will be used if the ::WIMStruct is later persisted + * to an on-disk file using wimlib_write(). *
* This choice is not necessarily final. If desired, it can still be * changed at any time before wimlib_write() is called, using @@ -2626,7 +2625,7 @@ wimlib_add_tree(WIMStruct *wim, int image, * Insufficient memory to allocate a new ::WIMStruct. */ extern int -wimlib_create_new_wim(int ctype, WIMStruct **wim_ret); +wimlib_create_new_wim(enum wimlib_compression_type ctype, WIMStruct **wim_ret); /** * @ingroup G_modifying_wims @@ -3046,7 +3045,7 @@ wimlib_free(WIMStruct *wim); * Convert a ::wimlib_compression_type value into a string. * * @param ctype - * The ::wimlib_compression_type value to convert. + * The compression type value to convert. * * @return * A statically allocated string naming the compression type, such as @@ -3054,7 +3053,7 @@ wimlib_free(WIMStruct *wim); * the resulting string will be "Invalid". */ extern const wimlib_tchar * -wimlib_get_compression_type_string(int ctype); +wimlib_get_compression_type_string(enum wimlib_compression_type ctype); /** * @ingroup G_general @@ -4018,11 +4017,9 @@ wimlib_set_output_pack_chunk_size(WIMStruct *wim, uint32_t chunk_size); * @param wim * The ::WIMStruct for which to set the output compression type. * @param ctype - * The compression type to set (one of ::wimlib_compression_type). If this - * compression type is incompatible with the current output chunk size - * (either the default or as set with wimlib_set_output_chunk_size()), then - * the output chunk size will be reset to the default for that compression - * type. + * The compression type to set. If this compression type is incompatible + * with the current output chunk size, then the output chunk size will be + * reset to the default for the new compression type. * * @return 0 on success; a ::wimlib_error_code value on failure. * @@ -4030,16 +4027,18 @@ wimlib_set_output_pack_chunk_size(WIMStruct *wim, uint32_t chunk_size); * @p ctype did not specify a valid compression type. */ extern int -wimlib_set_output_compression_type(WIMStruct *wim, int ctype); +wimlib_set_output_compression_type(WIMStruct *wim, + enum wimlib_compression_type ctype); /** * @ingroup G_writing_and_overwriting_wims * * Similar to wimlib_set_output_compression_type(), but set the compression type - * for writing solid resources. + * for writing solid resources. This cannot be ::WIMLIB_COMPRESSION_TYPE_NONE. */ extern int -wimlib_set_output_pack_compression_type(WIMStruct *wim, int ctype); +wimlib_set_output_pack_compression_type(WIMStruct *wim, + enum wimlib_compression_type ctype); /** * @ingroup G_general diff --git a/include/wimlib/wim.h b/include/wimlib/wim.h index cb330a21..09c65123 100644 --- a/include/wimlib/wim.h +++ b/include/wimlib/wim.h @@ -185,11 +185,12 @@ static inline bool wim_is_pipable(const WIMStruct *wim) extern bool wim_has_solid_resources(const WIMStruct *wim); -extern int -set_wim_hdr_cflags(int ctype, struct wim_header *hdr); +extern void +set_wim_hdr_cflags(enum wimlib_compression_type ctype, struct wim_header *hdr); -extern int -init_wim_header(struct wim_header *hdr, int ctype, u32 chunk_size); +extern void +init_wim_header(struct wim_header *hdr, + enum wimlib_compression_type ctype, u32 chunk_size); extern int read_wim_header(WIMStruct *wim, struct wim_header *hdr); diff --git a/src/header.c b/src/header.c index 21dec59a..254b48bd 100644 --- a/src/header.c +++ b/src/header.c @@ -216,66 +216,53 @@ write_wim_header_flags(u32 hdr_flags, struct filedes *out_fd) offsetof(struct wim_header_disk, wim_flags)); } -int -set_wim_hdr_cflags(int ctype, struct wim_header *hdr) +void +set_wim_hdr_cflags(enum wimlib_compression_type ctype, struct wim_header *hdr) { hdr->flags &= ~(WIM_HDR_FLAG_COMPRESSION | - WIM_HDR_FLAG_COMPRESS_LZX | WIM_HDR_FLAG_COMPRESS_RESERVED | WIM_HDR_FLAG_COMPRESS_XPRESS | + WIM_HDR_FLAG_COMPRESS_LZX | WIM_HDR_FLAG_COMPRESS_LZMS | WIM_HDR_FLAG_COMPRESS_XPRESS_2); switch (ctype) { - case WIMLIB_COMPRESSION_TYPE_NONE: - return 0; - - case WIMLIB_COMPRESSION_TYPE_LZX: - hdr->flags |= WIM_HDR_FLAG_COMPRESSION | WIM_HDR_FLAG_COMPRESS_LZX; - return 0; - + return; case WIMLIB_COMPRESSION_TYPE_XPRESS: hdr->flags |= WIM_HDR_FLAG_COMPRESSION | WIM_HDR_FLAG_COMPRESS_XPRESS; - return 0; - + return; + case WIMLIB_COMPRESSION_TYPE_LZX: + hdr->flags |= WIM_HDR_FLAG_COMPRESSION | WIM_HDR_FLAG_COMPRESS_LZX; + return; case WIMLIB_COMPRESSION_TYPE_LZMS: hdr->flags |= WIM_HDR_FLAG_COMPRESSION | WIM_HDR_FLAG_COMPRESS_LZMS; - return 0; - - default: - return WIMLIB_ERR_INVALID_COMPRESSION_TYPE; + return; } + wimlib_assert(0); } -/* - * Initializes the header for a WIM file. - */ -int -init_wim_header(struct wim_header *hdr, int ctype, u32 chunk_size) +/* Initialize the header for a WIM file. */ +void +init_wim_header(struct wim_header *hdr, + enum wimlib_compression_type ctype, u32 chunk_size) { memset(hdr, 0, sizeof(struct wim_header)); hdr->magic = WIM_MAGIC; - if (ctype == WIMLIB_COMPRESSION_TYPE_LZMS) hdr->wim_version = WIM_VERSION_SOLID; else hdr->wim_version = WIM_VERSION_DEFAULT; - if (set_wim_hdr_cflags(ctype, hdr)) { - ERROR("Invalid compression type specified (%d)", ctype); - return WIMLIB_ERR_INVALID_COMPRESSION_TYPE; - } + set_wim_hdr_cflags(ctype, hdr); hdr->chunk_size = chunk_size; hdr->total_parts = 1; hdr->part_number = 1; randomize_byte_array(hdr->guid, sizeof(hdr->guid)); - return 0; } -struct hdr_flag { +static const struct { u32 flag; const char *name; -}; -struct hdr_flag hdr_flags[] = { +} hdr_flags[] = { {WIM_HDR_FLAG_RESERVED, "RESERVED"}, {WIM_HDR_FLAG_COMPRESSION, "COMPRESSION"}, {WIM_HDR_FLAG_READONLY, "READONLY"}, diff --git a/src/wim.c b/src/wim.c index 9b776023..6522d7bc 100644 --- a/src/wim.c +++ b/src/wim.c @@ -3,7 +3,7 @@ */ /* - * Copyright (C) 2012, 2013, 2014 Eric Biggers + * Copyright (C) 2012, 2013, 2014, 2015 Eric Biggers * * This file is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free @@ -35,7 +35,6 @@ #include "wimlib.h" #include "wimlib/assert.h" #include "wimlib/blob_table.h" -#include "wimlib/bitops.h" #include "wimlib/dentry.h" #include "wimlib/encoding.h" #include "wimlib/file_io.h" @@ -51,97 +50,84 @@ # include "wimlib/win32.h" /* for realpath() replacement */ #endif -static int -wim_default_solid_compression_type(void) +/* Information about the available compression types for the WIM format. */ +static const struct { + const tchar *name; + u32 min_chunk_size; + u32 max_chunk_size; + u32 default_nonsolid_chunk_size; + u32 default_solid_chunk_size; +} wim_ctype_info[] = { + [WIMLIB_COMPRESSION_TYPE_NONE] = { + .name = T("None"), + .min_chunk_size = 0, + .max_chunk_size = 0, + .default_nonsolid_chunk_size = 0, + .default_solid_chunk_size = 0, + }, + [WIMLIB_COMPRESSION_TYPE_XPRESS] = { + .name = T("XPRESS"), + .min_chunk_size = 4096, + .max_chunk_size = 65536, + .default_nonsolid_chunk_size = 32768, + .default_solid_chunk_size = 32768, + }, + [WIMLIB_COMPRESSION_TYPE_LZX] = { + .name = T("LZX"), + .min_chunk_size = 32768, + .max_chunk_size = 2097152, + .default_nonsolid_chunk_size = 32768, + .default_solid_chunk_size = 32768, + }, + [WIMLIB_COMPRESSION_TYPE_LZMS] = { + .name = T("LZMS"), + .min_chunk_size = 32768, + .max_chunk_size = 1073741824, + .default_nonsolid_chunk_size = 131072, + .default_solid_chunk_size = 67108864, + }, +}; + +/* Is the specified compression type valid? */ +static bool +wim_compression_type_valid(enum wimlib_compression_type ctype) { - return WIMLIB_COMPRESSION_TYPE_LZMS; + return ctype >= 0 && ctype < ARRAY_LEN(wim_ctype_info) && + wim_ctype_info[ctype].name != NULL; } -static u32 -wim_default_solid_chunk_size(int ctype) { - switch (ctype) { - case WIMLIB_COMPRESSION_TYPE_LZMS: - return (u32)1 << 26; /* 67108864 */ - default: - return (u32)1 << 15; /* 32768 */ - } -} - -static WIMStruct * -new_wim_struct(void) +/* Is the specified chunk size valid for the compression type? */ +static bool +wim_chunk_size_valid(u32 chunk_size, enum wimlib_compression_type ctype) { - WIMStruct *wim = CALLOC(1, sizeof(WIMStruct)); - if (!wim) - return NULL; + if (!(chunk_size == 0 || is_power_of_2(chunk_size))) + return false; - filedes_invalidate(&wim->in_fd); - filedes_invalidate(&wim->out_fd); - wim->out_solid_compression_type = wim_default_solid_compression_type(); - wim->out_solid_chunk_size = wim_default_solid_chunk_size( - wim->out_solid_compression_type); - INIT_LIST_HEAD(&wim->subwims); - return wim; + return chunk_size >= wim_ctype_info[ctype].min_chunk_size && + chunk_size <= wim_ctype_info[ctype].max_chunk_size; } -/* Determine if the chunk size is valid for the specified compression type. */ -static bool -wim_chunk_size_valid(u32 chunk_size, int ctype) +/* Return the default chunk size to use for the specified compression type in + * non-solid resources. */ +static u32 +wim_default_nonsolid_chunk_size(enum wimlib_compression_type ctype) { - u32 order; - - /* Chunk size is meaningless for uncompressed WIMs --- any value is - * okay. */ - if (ctype == WIMLIB_COMPRESSION_TYPE_NONE) - return true; - - /* Chunk size must be power of 2. */ - if (chunk_size == 0) - return false; - order = fls32(chunk_size); - if (chunk_size != 1U << order) - return false; - - /* Order Size - * ===== ==== - * 15 32768 - * 16 65536 - * 17 131072 - * 18 262144 - * 19 524288 - * 20 1048576 - * 21 2097152 - * 22 4194304 - * 23 8388608 - * 24 16777216 - * 25 33554432 - * 26 67108864 - */ - - /* See the documentation for the --chunk-size option of `wimlib-imagex - * capture' for information about allowed chunk sizes. */ - switch (ctype) { - case WIMLIB_COMPRESSION_TYPE_LZX: - return order >= 15 && order <= 21; - case WIMLIB_COMPRESSION_TYPE_XPRESS: - return order >= 12 && order <= 16; - case WIMLIB_COMPRESSION_TYPE_LZMS: - return order >= 15 && order <= 30; - } - return false; + return wim_ctype_info[ctype].default_nonsolid_chunk_size; } -/* Return the default chunk size to use for the specified compression type. - * - * See notes above in wim_chunk_size_valid(). */ +/* Return the default chunk size to use for the specified compression type in + * solid resources. */ static u32 -wim_default_chunk_size(int ctype) +wim_default_solid_chunk_size(enum wimlib_compression_type ctype) { - switch (ctype) { - case WIMLIB_COMPRESSION_TYPE_LZMS: - return 1U << 17; /* 131072 */ - default: - return 1U << 15; /* 32768 */ - } + return wim_ctype_info[ctype].default_solid_chunk_size; +} + +/* Return the default compression type to use in solid resources. */ +static enum wimlib_compression_type +wim_default_solid_compression_type(void) +{ + return WIMLIB_COMPRESSION_TYPE_LZMS; } static int @@ -157,46 +143,28 @@ wim_has_solid_resources(const WIMStruct *wim) return for_blob_in_table(wim->blob_table, is_blob_in_solid_resource, NULL); } -/* - * Calls a function on images in the WIM. If @image is WIMLIB_ALL_IMAGES, - * @visitor is called on the WIM once for each image, with each image selected - * as the current image in turn. If @image is a certain image, @visitor is - * called on the WIM only once, with that image selected. - */ -int -for_image(WIMStruct *wim, int image, int (*visitor)(WIMStruct *)) +static WIMStruct * +new_wim_struct(void) { - int ret; - int start; - int end; - int i; + WIMStruct *wim = CALLOC(1, sizeof(WIMStruct)); + if (!wim) + return NULL; - if (image == WIMLIB_ALL_IMAGES) { - start = 1; - end = wim->hdr.image_count; - } else if (image >= 1 && image <= wim->hdr.image_count) { - start = image; - end = image; - } else { - return WIMLIB_ERR_INVALID_IMAGE; - } - for (i = start; i <= end; i++) { - ret = select_wim_image(wim, i); - if (ret != 0) - return ret; - ret = visitor(wim); - if (ret != 0) - return ret; - } - return 0; + filedes_invalidate(&wim->in_fd); + filedes_invalidate(&wim->out_fd); + wim->out_solid_compression_type = wim_default_solid_compression_type(); + wim->out_solid_chunk_size = wim_default_solid_chunk_size( + wim->out_solid_compression_type); + INIT_LIST_HEAD(&wim->subwims); + return wim; } /* API function documented in wimlib.h */ WIMLIBAPI int -wimlib_create_new_wim(int ctype, WIMStruct **wim_ret) +wimlib_create_new_wim(enum wimlib_compression_type ctype, WIMStruct **wim_ret) { - WIMStruct *wim; int ret; + WIMStruct *wim; ret = wimlib_global_init(WIMLIB_INIT_FLAG_ASSUME_UTF8); if (ret) @@ -205,29 +173,28 @@ wimlib_create_new_wim(int ctype, WIMStruct **wim_ret) if (!wim_ret) return WIMLIB_ERR_INVALID_PARAM; + if (!wim_compression_type_valid(ctype)) + return WIMLIB_ERR_INVALID_COMPRESSION_TYPE; + wim = new_wim_struct(); if (!wim) return WIMLIB_ERR_NOMEM; - ret = init_wim_header(&wim->hdr, ctype, wim_default_chunk_size(ctype)); - if (ret) - goto out_free_wim; - wim->blob_table = new_blob_table(9001); if (!wim->blob_table) { - ret = WIMLIB_ERR_NOMEM; - goto out_free_wim; + wimlib_free(wim); + return WIMLIB_ERR_NOMEM; } + + init_wim_header(&wim->hdr, ctype, + wim_default_nonsolid_chunk_size(ctype)); wim->compression_type = ctype; wim->out_compression_type = ctype; wim->chunk_size = wim->hdr.chunk_size; wim->out_chunk_size = wim->hdr.chunk_size; + *wim_ret = wim; return 0; - -out_free_wim: - FREE(wim); - return ret; } static void @@ -384,22 +351,38 @@ deselect_current_wim_image(WIMStruct *wim) wim->current_image = WIMLIB_NO_IMAGE; } -/* API function documented in wimlib.h */ -WIMLIBAPI const tchar * -wimlib_get_compression_type_string(int ctype) +/* + * Calls a function on images in the WIM. If @image is WIMLIB_ALL_IMAGES, + * @visitor is called on the WIM once for each image, with each image selected + * as the current image in turn. If @image is a certain image, @visitor is + * called on the WIM only once, with that image selected. + */ +int +for_image(WIMStruct *wim, int image, int (*visitor)(WIMStruct *)) { - switch (ctype) { - case WIMLIB_COMPRESSION_TYPE_NONE: - return T("None"); - case WIMLIB_COMPRESSION_TYPE_XPRESS: - return T("XPRESS"); - case WIMLIB_COMPRESSION_TYPE_LZX: - return T("LZX"); - case WIMLIB_COMPRESSION_TYPE_LZMS: - return T("LZMS"); - default: - return T("Invalid"); + int ret; + int start; + int end; + int i; + + if (image == WIMLIB_ALL_IMAGES) { + start = 1; + end = wim->hdr.image_count; + } else if (image >= 1 && image <= wim->hdr.image_count) { + start = image; + end = image; + } else { + return WIMLIB_ERR_INVALID_IMAGE; + } + for (i = start; i <= end; i++) { + ret = select_wim_image(wim, i); + if (ret != 0) + return ret; + ret = visitor(wim); + if (ret != 0) + return ret; } + return 0; } /* API function documented in wimlib.h */ @@ -524,41 +507,35 @@ wimlib_set_wim_info(WIMStruct *wim, const struct wimlib_wim_info *info, int whic return 0; } -static int -set_out_ctype(int ctype, u8 *out_ctype_p) -{ - switch (ctype) { - case WIMLIB_COMPRESSION_TYPE_NONE: - case WIMLIB_COMPRESSION_TYPE_LZX: - case WIMLIB_COMPRESSION_TYPE_XPRESS: - case WIMLIB_COMPRESSION_TYPE_LZMS: - *out_ctype_p = ctype; - return 0; - } - return WIMLIB_ERR_INVALID_COMPRESSION_TYPE; -} - /* API function documented in wimlib.h */ WIMLIBAPI int -wimlib_set_output_compression_type(WIMStruct *wim, int ctype) +wimlib_set_output_compression_type(WIMStruct *wim, + enum wimlib_compression_type ctype) { - int ret = set_out_ctype(ctype, &wim->out_compression_type); - if (ret) - return ret; + if (!wim_compression_type_valid(ctype)) + return WIMLIB_ERR_INVALID_COMPRESSION_TYPE; + + wim->out_compression_type = ctype; /* Reset the chunk size if it's no longer valid. */ if (!wim_chunk_size_valid(wim->out_chunk_size, ctype)) - wim->out_chunk_size = wim_default_chunk_size(ctype); + wim->out_chunk_size = wim_default_nonsolid_chunk_size(ctype); return 0; } /* API function documented in wimlib.h */ WIMLIBAPI int -wimlib_set_output_pack_compression_type(WIMStruct *wim, int ctype) +wimlib_set_output_pack_compression_type(WIMStruct *wim, + enum wimlib_compression_type ctype) { - int ret = set_out_ctype(ctype, &wim->out_solid_compression_type); - if (ret) - return ret; + if (!wim_compression_type_valid(ctype)) + return WIMLIB_ERR_INVALID_COMPRESSION_TYPE; + + /* Solid resources can't be uncompressed. */ + if (ctype == WIMLIB_COMPRESSION_TYPE_NONE) + return WIMLIB_ERR_INVALID_COMPRESSION_TYPE; + + wim->out_solid_compression_type = ctype; /* Reset the chunk size if it's no longer valid. */ if (!wim_chunk_size_valid(wim->out_solid_chunk_size, ctype)) @@ -566,34 +543,26 @@ wimlib_set_output_pack_compression_type(WIMStruct *wim, int ctype) return 0; } -static int -set_out_chunk_size(u32 chunk_size, int ctype, u32 *out_chunk_size_p) -{ - if (!wim_chunk_size_valid(chunk_size, ctype)) - return WIMLIB_ERR_INVALID_CHUNK_SIZE; - - *out_chunk_size_p = chunk_size; - return 0; -} - /* API function documented in wimlib.h */ WIMLIBAPI int -wimlib_set_output_chunk_size(WIMStruct *wim, uint32_t chunk_size) +wimlib_set_output_chunk_size(WIMStruct *wim, u32 chunk_size) { if (chunk_size == 0) { wim->out_chunk_size = - wim_default_chunk_size(wim->out_compression_type); + wim_default_nonsolid_chunk_size(wim->out_compression_type); return 0; } - return set_out_chunk_size(chunk_size, - wim->out_compression_type, - &wim->out_chunk_size); + if (!wim_chunk_size_valid(chunk_size, wim->out_compression_type)) + return WIMLIB_ERR_INVALID_CHUNK_SIZE; + + wim->out_chunk_size = chunk_size; + return 0; } /* API function documented in wimlib.h */ WIMLIBAPI int -wimlib_set_output_pack_chunk_size(WIMStruct *wim, uint32_t chunk_size) +wimlib_set_output_pack_chunk_size(WIMStruct *wim, u32 chunk_size) { if (chunk_size == 0) { wim->out_solid_chunk_size = @@ -601,9 +570,21 @@ wimlib_set_output_pack_chunk_size(WIMStruct *wim, uint32_t chunk_size) return 0; } - return set_out_chunk_size(chunk_size, - wim->out_solid_compression_type, - &wim->out_solid_chunk_size); + if (!wim_chunk_size_valid(chunk_size, wim->out_solid_compression_type)) + return WIMLIB_ERR_INVALID_CHUNK_SIZE; + + wim->out_solid_chunk_size = chunk_size; + return 0; +} + +/* API function documented in wimlib.h */ +WIMLIBAPI const tchar * +wimlib_get_compression_type_string(enum wimlib_compression_type ctype) +{ + if (!wim_compression_type_valid(ctype)) + return T("Invalid"); + + return wim_ctype_info[ctype].name; } WIMLIBAPI void diff --git a/src/write.c b/src/write.c index ef78f9ca..30b063e5 100644 --- a/src/write.c +++ b/src/write.c @@ -2880,13 +2880,8 @@ write_wim_part(WIMStruct *wim, wim->hdr.part_number = part_number; wim->hdr.total_parts = total_parts; - /* Set compression type if different. */ - if (wim->compression_type != wim->out_compression_type) { - ret = set_wim_hdr_cflags(wim->out_compression_type, &wim->hdr); - wimlib_assert(ret == 0); - } - - /* Set chunk size if different. */ + /* Set the compression type and chunk size. */ + set_wim_hdr_cflags(wim->out_compression_type, &wim->hdr); wim->hdr.chunk_size = wim->out_chunk_size; /* Set GUID. */