/** * @brief Get a list of options applicable to the codec * * @param codec name of the codec * @return a list of options, terminated by an option with a NULL name */ const SquashOptionInfo* squash_get_option_info (const char* codec) { SquashCodec* codec_real = squash_get_codec (codec); if (codec_real != NULL) return squash_codec_get_option_info (codec_real); else return NULL; }
/** * @brief Get the maximum buffer size necessary to store compressed data. * * Typically the return value will be some percentage larger than the * uncompressed length, plus a few bytes. For example, for bzip2 it * is the uncompressed length plus 1%, plus an additional 600 bytes. * * @warning The result of this function is not guaranteed to be * correct for use with the @ref SquashStream API—it should only be * used with the single-squashl buffer-to-buffer functions such as * ::squash_codec_compress and ::squash_codec_compress_with_options. * * @param codec The name of the codec * @param uncompressed_length Size of the uncompressed data in bytes * @return The maximum size required to store a compressed buffer * representing @a uncompressed_length of uncompressed data. * @see squash_codec_get_max_compressed_size */ size_t squash_get_max_compressed_size (const char* codec, size_t uncompressed_length) { SquashCodec* codec_real = squash_get_codec (codec); if (codec_real == NULL) { return 0; } return squash_codec_get_max_compressed_size (codec_real, uncompressed_length); }
/** * @brief Open an existing stdio file with the specified options * * @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_codec * @see squash_file_steal_with_options * @see squash_file_steal_codec_with_options */ SquashFile* squash_file_steal_with_options (const char* codec, FILE* fp, SquashOptions* options) { assert (fp != NULL); assert (codec != NULL); SquashCodec* codec_i = squash_get_codec (codec); if (codec_i == NULL) return NULL; return squash_file_steal_codec_with_options (codec_i, fp, options); }
/** * @brief Get a bitmask of information about the codec * * @param codec The codec * @return the codec info, or @ref SQUASH_CODEC_INFO_INVALID if there * is no such codec */ SquashCodecInfo squash_get_info (const char* codec) { SquashCodec* codec_real = squash_get_codec (codec); if (codec_real != NULL) { return squash_codec_get_info (codec_real); } else { squash_error (SQUASH_NOT_FOUND); return SQUASH_CODEC_INFO_INVALID; } }
/** * @brief Open a file with the specified options * * @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 */ SquashFile* squash_file_open_with_options (const char* codec, const char* filename, const char* mode, SquashOptions* options) { assert (filename != NULL); assert (mode != NULL); assert (codec != NULL); SquashCodec* codec_i = squash_get_codec (codec); if (codec_i == NULL) return NULL; return squash_file_open_codec_with_options (codec_i, filename, mode, options); }
//---------- Codec::Codec(string codecName) { ofxSquash::initialize(); this->name = codecName; this->squashCodec = squash_get_codec(codecName.c_str()); if (this->squashCodec) { this->valid = true; } else { OFXSQUASH_WARNING << "Codec [" << this->name << "] cannot be initialized"; this->valid = false; } }
size_t squash_get_uncompressed_size (const char* codec, size_t compressed_length, const uint8_t compressed[SQUASH_ARRAY_PARAM(compressed_length)]) { assert (codec != NULL); assert (compressed_length > 0); assert (compressed != NULL); SquashCodec* codec_real = squash_get_codec (codec); if (codec_real == NULL) return 0; return squash_codec_get_uncompressed_size (codec_real, compressed_length, compressed); }
/** * @brief Decompress a buffer * * @param codec The name of the codec to use * @param[out] decompressed Location to store the decompressed data * @param[in,out] decompressed_length Location storing the size of the * @a decompressed buffer on input, replaced with the actual size of * the decompressed data * @param compressed The compressed data * @param compressed_length Length of the compressed data (in bytes) * @param options Decompression options, or *NULL* to use the defaults * @return A status code */ SquashStatus squash_decompress_with_options (const char* 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) { SquashCodec* codec_real = squash_get_codec (codec); if (codec_real == NULL) return squash_error (SQUASH_NOT_FOUND); return squash_codec_decompress_with_options (codec_real, decompressed_length, decompressed, compressed_length, compressed, options); }
/** * @brief Open an existing stdio file * * Note that Squash expects to have exclusive access to @a fp. When * possible, Squash will acquire @a fp's lock (using flockfile) in * this function and will not release it until the @ref SquashFile * instance is destroyed. * * @param fp the stdio file to use * @param codec codec to use * @param ... options * @return The opened file, or *NULL* on error * @see squash_file_steal_codec * @see squash_file_steal_with_options * @see squash_file_steal_codec_with_options */ SquashFile* squash_file_steal (const char* codec, FILE* fp, ...) { va_list ap; SquashOptions* options; assert (fp != NULL); assert (codec != NULL); SquashCodec* codec_i = squash_get_codec (codec); if (codec_i == NULL) return NULL; va_start (ap, fp); options = squash_options_newv (codec_i, ap); va_end (ap); return squash_file_steal_codec_with_options (codec_i, fp, options); }
static SquashCodec* benchmark_parse_codec (const char* str, SquashOptions** options) { SquashCodec* codec; char* s = strdup (str); char* sp_outer = NULL; char* sp_inner = NULL; char* cur_opt = NULL; char* cur_key = NULL; char* cur_val = NULL; SquashStatus res; char* name = strtok_r (s, "/", &sp_outer); codec = squash_get_codec (name); if (codec == NULL) return NULL; while ((cur_opt = strtok_r (NULL, ",", &sp_outer)) != NULL) { if (*options == NULL) { assert (codec != NULL); *options = squash_options_new (codec, NULL); squash_object_ref_sink (*options); } cur_key = strtok_r (cur_opt, "=", &sp_inner); cur_val = strtok_r (NULL, "=", &sp_inner); if (cur_val == NULL) { cur_val = cur_key; cur_key = "level"; } assert (*options != NULL); res = squash_options_parse_option (*options, cur_key, cur_val); if (res != SQUASH_OK) { fprintf (stderr, "Unable to parse options: %s (%d)\n", squash_status_to_string (res), res); exit (EXIT_FAILURE); } } free (s); return codec; }
/** * @brief Open a file * * The @a mode parameter will be passed through to @a fopen, so the * value must valid. Note that Squash may attempt to use @a mmap * regardless of whether the *m* flag is passed. * * The file is always assumed to be compressed—calling @ref * squash_file_write will always compress, and calling @ref * squash_file_read will always decompress. Note, however, that you * cannot mix reading and writing to the same file as you can with a * standard *FILE*. * * @note Error handling for this function is somewhat limited, and it * may be difficult to determine the exact nature of problems such as * an invalid codec, where errno is not set. If this is unacceptable * you should call @ref squash_get_codec and @ref squash_options_parse * yourself and pass the results to @ref * squash_file_open_codec_with_options (which will only fail due to * the underlying *fopen* failing). * * @param filename name of the file to open * @param mode file mode * @param codec codec to use * @param ... options * @return The opened file, or *NULL* on error * @see squash_file_open_codec * @see squash_file_open_with_options * @see squash_file_open_codec_with_options */ SquashFile* squash_file_open (const char* codec, const char* filename, const char* mode, ...) { va_list ap; SquashOptions* options; SquashCodec* codec_i; assert (filename != NULL); assert (mode != NULL); assert (codec != NULL); codec_i = squash_get_codec (codec); if (codec_i == NULL) return NULL; va_start (ap, mode); options = squash_options_newv (codec_i, ap); va_end (ap); return squash_file_open_codec_with_options (codec_i, filename, mode, options); }
/** * @brief Decompress a buffer with an existing @ref SquashOptions * * @param codec The name of the codec to use * @param[out] decompressed Location to store the decompressed data * @param[in,out] decompressed_length Location storing the size of the * @a decompressed buffer on input, replaced with the actual size of * the decompressed data * @param compressed The compressed data * @param compressed_length Length of the compressed data (in bytes) * @param ... A variadic list of key/value option pairs, followed by * *NULL* * @return A status code */ SquashStatus squash_decompress (const char* 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; va_list ap; SquashCodec* codec_real = squash_get_codec (codec); if (codec_real == NULL) return squash_error (SQUASH_NOT_FOUND); va_start (ap, compressed); options = squash_options_newv (codec_real, ap); va_end (ap); return squash_codec_decompress_with_options (codec_real, decompressed_length, decompressed, compressed_length, compressed, options); }
int main (int argc, char** argv) { SquashStatus res; SquashCodec* codec = NULL; SquashOptions* options = NULL; SquashStreamType direction = SQUASH_STREAM_COMPRESS; FILE* input = NULL; FILE* output = NULL; char* input_name = NULL; char* output_name = NULL; bool list_codecs = false; bool list_plugins = false; char** option_keys = NULL; char** option_values = NULL; bool keep = false; bool force = false; int opt; int optc = 0; char* tmp_string; int retval = EXIT_SUCCESS; struct parg_state ps; int optend; const struct parg_option squash_options[] = { {"keep", PARG_NOARG, NULL, 'k'}, {"option", PARG_REQARG, NULL, 'o'}, {"codec", PARG_REQARG, NULL, 'c'}, {"list-codecs", PARG_NOARG, NULL, 'L'}, {"list-plugins", PARG_NOARG, NULL, 'P'}, {"force", PARG_NOARG, NULL, 'f'}, {"decompress", PARG_NOARG, NULL, 'd'}, {"version", PARG_NOARG, NULL, 'V'}, {"help", PARG_NOARG, NULL, 'h'}, {NULL, 0, NULL, 0} }; option_keys = (char**) malloc (sizeof (char*)); option_values = (char**) malloc (sizeof (char*)); *option_keys = NULL; *option_values = NULL; optend = parg_reorder (argc, argv, "c:ko:123456789LPfdhb:V", squash_options); parg_init(&ps); while ( (opt = parg_getopt_long (&ps, optend, argv, "c:ko:123456789LPfdhb:V", squash_options, NULL)) != -1 ) { switch ( opt ) { case 'c': codec = squash_get_codec (ps.optarg); if ( codec == NULL ) { fprintf (stderr, "Unable to find codec '%s'\n", ps.optarg); retval = exit_failure (); goto cleanup; } break; case 'k': keep = true; break; case 'o': parse_option (&option_keys, &option_values, ps.optarg); break; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': tmp_string = malloc (8); snprintf (tmp_string, 8, "level=%c", (char) opt); parse_option (&option_keys, &option_values, tmp_string); free (tmp_string); break; case 'L': list_codecs = true; break; case 'P': list_plugins = true; break; case 'f': force = true; break; case 'h': print_help_and_exit (argc, argv, EXIT_SUCCESS); break; case 'd': direction = SQUASH_STREAM_DECOMPRESS; break; case 'V': print_version_and_exit (argc, argv, EXIT_SUCCESS); break; } optc++; } if (list_plugins) { if (list_codecs) squash_foreach_plugin (list_plugins_and_codecs_foreach_cb, NULL); else squash_foreach_plugin (list_plugins_foreach_cb, NULL); goto cleanup; } else if (list_codecs) { squash_foreach_codec (list_codecs_foreach_cb, NULL); goto cleanup; } if ( ps.optind < argc ) { input_name = argv[ps.optind++]; if ( (direction == SQUASH_STREAM_DECOMPRESS) && codec == NULL ) { char* extension; extension = strrchr (input_name, '.'); if (extension != NULL) extension++; if (extension != NULL) codec = squash_get_codec_from_extension (extension); } } else { fprintf (stderr, "You must provide an input file name.\n"); retval = exit_failure (); goto cleanup; } if ( ps.optind < argc ) { output_name = strdup (argv[ps.optind++]); if ( codec == NULL && direction == SQUASH_STREAM_COMPRESS ) { const char* extension = strrchr (output_name, '.'); if (extension != NULL) extension++; if (extension != NULL) codec = squash_get_codec_from_extension (extension); } } else { if ( codec != NULL ) { const char* extension = squash_codec_get_extension (codec); if (extension != NULL) { if (strcmp (input_name, "-") == 0) { output_name = strdup ("-"); } else { size_t extension_length = strlen (extension); size_t input_name_length = strlen (input_name); if ( (extension_length + 1) < input_name_length && input_name[input_name_length - (1 + extension_length)] == '.' && strcasecmp (extension, input_name + (input_name_length - (extension_length))) == 0 ) { output_name = squash_strndup (input_name, input_name_length - (1 + extension_length)); } } } } } if ( ps.optind < argc ) { fprintf (stderr, "Too many arguments.\n"); } if ( codec == NULL ) { fprintf (stderr, "Unable to determine codec. Please pass -c \"codec\", or -L to see a list of available codecs.\n"); retval = exit_failure (); goto cleanup; } if ( output_name == NULL ) { fprintf (stderr, "Unable to determine output file.\n"); retval = exit_failure (); goto cleanup; } if ( strcmp (input_name, "-") == 0 ) { input = stdin; } else { input = fopen (input_name, "rb"); if ( input == NULL ) { perror ("Unable to open input file"); retval = exit_failure (); goto cleanup; } } if ( strcmp (output_name, "-") == 0 ) { output = stdout; } else { int output_fd = open (output_name, #if !defined(_WIN32) O_RDWR | O_CREAT | (force ? O_TRUNC : O_EXCL), S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH #else O_RDWR | O_CREAT | (force ? O_TRUNC : O_EXCL) | O_BINARY, S_IREAD | S_IWRITE #endif ); if ( output_fd < 0 ) { perror ("Unable to open output file"); retval = exit_failure (); goto cleanup; } output = fdopen (output_fd, "wb"); if ( output == NULL ) { perror ("Unable to open output"); retval = exit_failure (); goto cleanup; } } options = squash_options_newa (codec, (const char * const*) option_keys, (const char * const*) option_values); res = squash_splice_with_options (codec, direction, output, input, 0, options); if ( res != SQUASH_OK ) { fprintf (stderr, "Failed to %s: %s\n", (direction == SQUASH_STREAM_COMPRESS) ? "compress" : "decompress", squash_status_to_string (res)); retval = exit_failure (); goto cleanup; } if ( !keep && input != stdin ) { fclose (input); if ( unlink (input_name) != 0 ) { perror ("Unable to remove input file"); } input = NULL; } cleanup: if (input != stdin && input != NULL) fclose (stdin); if (output != stdout) fclose (stdout); if (option_keys != NULL) { for (opt = 0 ; option_keys[opt] != NULL ; opt++) { free(option_keys[opt]); } free (option_keys); } if (option_values != NULL) { for (opt = 0 ; option_values[opt] != NULL ; opt++) { free(option_values[opt]); } free (option_values); } free (output_name); return retval; }
int main(int argc, char *argv[]) { int ret; off_t size = 0, size_c = 0; size_t len, len_c; FILE *in; void *in_buf, *out_buf; uint64_t full_len, out_len; struct stat st; void *in_map = NULL; void *out_map = NULL; int out_fd; double time = 0.0; #ifdef USE_MMAP uint64_t out_mapped; #endif struct timespec start, stop, start_full, stop_full; if (argc < 4 || argc > 6) help(); if (argc == 5 || argc == 6) assert(*argv[1] == 's'); if (strlen(argv[1]) != 1) help(); //file handling in = fopen(argv[2], "r"); assert(in); out_fd = open(argv[3], O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); assert(out_fd != -1); fstat(fileno(in), &st); full_len = st.st_size; #ifdef USE_MMAP switch(argv[1][0]) { case 'e' : out_mapped = full_len*2; break; case 'd' : out_mapped = CHUNK_SIZE*8; break; case 'm' : out_mapped = full_len; break; } #endif //initialisation #ifndef USE_MMAP_READ in_buf = malloc(CHUNK_SIZE); #else in_map = mmap(NULL, full_len, PROT_READ, MAP_SHARED, fileno(in), 0); if (in_map == MAP_FAILED) { printf("WARNING: mmap failed for %s, using regular write\n", argv[2]); in_map = NULL; in_buf = malloc(2*CHUNK_SIZE); } else in_buf = in_map; #endif #ifndef USE_MMAP_WRITE out_buf = malloc(2*CHUNK_SIZE); #else ftruncate(out_fd, out_mapped); out_map = mmap(NULL, out_mapped, PROT_WRITE, MAP_SHARED, out_fd, 0); if (out_map == MAP_FAILED) { printf("WARNING: mmap failed for %s, using regular write\n", argv[3]); out_map = NULL; out_buf = malloc(2*CHUNK_SIZE); } else out_buf = out_map; #endif switch(argv[1][0]) { #ifdef BBP_USE_SIMDCOMP case 'e' : clock_gettime(CLOCK_MONOTONIC, &start_full); #ifndef USE_MMAP_READ while ((len = fread(in_buf, 1, CHUNK_SIZE, in))) { #else for(in_buf=in_map;in_buf-in_map<full_len;in_buf+=CHUNK_SIZE) { len = full_len - (in_buf-in_map); if (len > CHUNK_SIZE) len = CHUNK_SIZE; if (len % (128*4)) break; #endif int b; clock_gettime(CLOCK_MONOTONIC, &start); //compression for(b=0;b<BENCHMARK_ITERATIONS;b++) len_c = compress(in_buf, len/4, out_buf); clock_gettime(CLOCK_MONOTONIC, &stop); time += ms_delta(start, stop); size += len; size_c += len_c; if (!out_map) { len = write(out_fd, out_buf, len_c); assert(len == len_c); } else out_buf += len_c; } out_len = size_c; clock_gettime(CLOCK_MONOTONIC, &stop_full); printf("compressed at %.3f MB/s / %.3fMB/s ratio %.2f\n",(float)size*BENCHMARK_ITERATIONS/1024/1024*1000/time, (float)size/1024/1024*1000/ms_delta(start_full, stop_full), (float)size/size_c); printf("%.2f %.3f simdcomp\n",(float)size/size_c, (float)size*BENCHMARK_ITERATIONS/1024/1024*1000/time); break; #endif #ifdef BBP_USE_SQUASH case 's' : assert(argc == 5 || argc == 6); SquashCodec* codec = squash_get_codec(argv[4]); SquashOptions *options; assert(codec); if (argc == 6) { options = squash_options_new(codec, NULL); ret = squash_options_parse_option(options, "level", argv[5]); if (ret != SQUASH_OK) { if (ret == SQUASH_BAD_PARAM) printf("ERROR: SQUASH: bad param\n"); if (ret == SQUASH_BAD_VALUE) printf("ERROR: SQUASH: bad value\n"); break; } } else options = NULL; clock_gettime(CLOCK_MONOTONIC, &start_full); #ifndef USE_MMAP_READ while ((len = fread(in_buf, 1, CHUNK_SIZE, in))) { #else for(in_buf=in_map;in_buf-in_map<full_len;in_buf+=CHUNK_SIZE) { len = full_len - (in_buf-in_map); if (len > CHUNK_SIZE) len = CHUNK_SIZE; #endif clock_gettime(CLOCK_MONOTONIC, &start); //compression len_c = 2*CHUNK_SIZE; if (options) squash_codec_compress_with_options(codec, &len_c, out_buf, len, in_buf, options); else ret = squash_compress(argv[4], &len_c, out_buf, len, in_buf, NULL); if (ret != SQUASH_OK) printf("ERROR: SQUASH (%s): %s\n",squash_status_to_string(ret), argv[4]); clock_gettime(CLOCK_MONOTONIC, &stop); time += ms_delta(start, stop); size += len; size_c += len_c; if (!out_map) { len = write(out_fd, out_buf, len_c); assert(len == len_c); } else out_buf += len_c; } out_len = size_c; clock_gettime(CLOCK_MONOTONIC, &stop_full); printf("compressed at %.3fMB/s / %.3fMB/s ratio %.2f\n",(float)size/1024/1024*1000/time, (float)size/1024/1024*1000/ms_delta(start_full, stop_full), (float)size/size_c); printf("%.2f %.3f %s\n",(float)size/size_c, (float)size/1024/1024*1000/time, argv[4]); break; #endif } if (in_map) munmap(in_map, full_len); fclose(in); if (out_map) munmap(out_map, full_len*2); ftruncate(out_fd, out_len); close(out_fd); return EXIT_SUCCESS; }
int main (int argc, char** argv) { SquashCodec* codec; const char* uncompressed; size_t uncompressed_length; size_t compressed_length; uint8_t* compressed; size_t decompressed_length; char* decompressed; if (argc != 3) { fprintf (stderr, "USAGE: %s ALGORITHM STRING\n", argv[0]); return EXIT_FAILURE; } codec = squash_get_codec (argv[1]); if (codec == NULL) { fprintf (stderr, "Unable to find algorithm '%s'.\n", argv[1]); return EXIT_FAILURE; } uncompressed = argv[2]; uncompressed_length = strlen (uncompressed); compressed_length = squash_codec_get_max_compressed_size (codec, uncompressed_length); compressed = (uint8_t*) malloc (compressed_length); decompressed_length = uncompressed_length + 1; decompressed = (char*) malloc (uncompressed_length + 1); SquashStatus res = squash_codec_compress (codec, &compressed_length, compressed, uncompressed_length, (const uint8_t*) uncompressed, NULL); if (res != SQUASH_OK) { fprintf (stderr, "Unable to compress data [%d]: %s\n", res, squash_status_to_string (res)); return EXIT_FAILURE; } fprintf (stdout, "Compressed a %u byte buffer to %u bytes.\n", (unsigned int) uncompressed_length, (unsigned int) compressed_length); res = squash_codec_decompress (codec, &decompressed_length, (uint8_t*) decompressed, compressed_length, compressed, NULL); if (res != SQUASH_OK) { fprintf (stderr, "Unable to decompress data [%d]: %s\n", res, squash_status_to_string (res)); return EXIT_FAILURE; } /* Notice that we didn't compress the *NULL* byte at the end of the string. We could have, it's just a waste to do so. */ decompressed[decompressed_length] = '\0'; if (strcmp (decompressed, uncompressed) != 0) { fprintf (stderr, "Bad decompressed data.\n"); EXIT_FAILURE; } fprintf (stdout, "Successfully decompressed.\n"); return EXIT_SUCCESS; }